<?php

namespace App\Repositories\ApiRpositories;

use App\Interfaces\ApiInterface\ChecklistRepositoryInterface;
use App\Models\Daily;
use App\Models\DetailDaily;
use App\Models\Form;
use App\Models\Location;
use App\Models\Shift;
use App\Models\Status;
use App\Models\Unit;
use Illuminate\Support\Facades\DB;
use Carbon\Carbon;
use Barryvdh\DomPDF\Facade\Pdf;
use Illuminate\Support\Facades\File;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Storage;
use PermissionHelper;

class ChecklistRepository implements ChecklistRepositoryInterface
{
    public function getFormsWithUncheckedUnits()
    {
        $today = Carbon::today();
        $user = auth()->user();

        $isOperator = optional($user->role)->isOperator;
        $allAccess = PermissionHelper::hasAllAccess();

        $forms = Form::with(['user'])
            ->FilterByRole()
            ->get()
            ->map(function ($form) use ($today, $user, $isOperator, $allAccess) {

                $units = DB::table('units')
                    ->join('type_units', 'units.type_id', '=', 'type_units.id')
                    ->when($isOperator === 1, function ($query) {
                        $query->whereIn('type_units.id', [4, 5]);
                    })
                    ->when($isOperator === 0, function ($query) {
                        $query->whereNotIn('type_units.id', [4, 5]);
                    })
                    ->when(!$allAccess, function ($query) use ($user) {
                        $query->where("location_id", $user->location_id);
                    })
                    ->pluck('units.id');

                $dailiesToday = DB::table('dailies')
                    ->where('form_id', $form->id)
                    ->whereDate('date', $today)
                    ->when(!$allAccess, function ($query) use ($user) {
                        $query->where("location_id", $user->location_id);
                    })
                    ->pluck('id');

                $checkedUnits = DB::table('detail_dailies')
                    ->whereIn('dailies_id', $dailiesToday)
                    ->whereIn('unit_id', $units)
                    ->pluck('unit_id')
                    ->unique();

                $uncheckedUnits = $units->diff($checkedUnits)->values();

                return [
                    'id' => $form->id,
                    'title' => $form->title,
                    'note' => $form->catatan,
                    'typeunit' => $form->type_unit->name ?? null,
                    'unit_belum_checklist' => $uncheckedUnits->count(),
                ];
            });

        return $forms;
    }


    public function getFormDetail($formId, $unitId, $shiftId)
    {
        $form = Form::findOrFail($formId);
        $today = Carbon::today();

        $sections = DB::table('form_section')
            ->where('form_id', $formId)
            ->select('id', 'name')
            ->get();

        $sectionIds = $sections->pluck('id');

        $items = DB::table('form_items')
            ->whereIn('form_section_id', $sectionIds)
            ->select('id', 'form_section_id', 'name')
            ->get();

        $itemIds = $items->pluck('id');

        $dailies = DB::table('dailies')
            ->where('form_id', $formId)
            ->where('unit_id', $unitId)
            ->where('shift_id', $shiftId)
            ->whereDate('date', $today)
            ->pluck('id');

        $answers = DB::table('detail_dailies')
            ->whereIn('dailies_id', $dailies)
            ->select('dailies_id', 'form_item_id', 'status_id', 'note')
            ->get()
            ->groupBy('form_item_id');

        $statuses = DB::table('form_item_statuses')
            ->join('status', 'status.id', '=', 'form_item_statuses.status_id')
            ->whereIn('form_item_id', $itemIds)
            ->select('form_item_statuses.form_item_id', 'status.id as status_id', 'status.name as status_name')
            ->get()
            ->groupBy('form_item_id');

        $sectionsData = $sections->map(function ($section) use ($items, $answers, $statuses) {
            $sectionItems = $items->where('form_section_id', $section->id)->map(function ($item) use ($answers, $statuses) {
                $answer = $answers->get($item->id)?->first();
                $availableStatuses = $statuses->get($item->id)?->map(function ($status) {
                    return [
                        'id' => $status->status_id,
                        'name' => $status->status_name,
                    ];
                }) ?? collect();

                return [
                    'id' => $item->id,
                    'name' => $item->name,
                    'answered' => $answer ? true : false,
                    'status_id' => $answer->status_id ?? null,
                    'note' => $answer->note ?? null,
                    'available_statuses' => $availableStatuses->values(),
                ];
            });

            return [
                'id' => $section->id,
                'name' => $section->name,
                'questions' => $sectionItems->values(),
            ];
        });

        return $sectionsData;
    }

    public function getShift()
    {
        $shifts = DB::table('shifts')
            ->select('id', 'name')
            ->get();

        return $shifts;
    }

    public function getHistory($userId = null, $isAdmin = false, $shiftId = null, $sitesId = null, $date = null, $search = null)
    {
        $date = $date ?? now();
        $allAccess = PermissionHelper::hasAllAccess();
        $query = Daily::select([
            'dailies.id',
            'dailies.code_report',
            'units.unit_code',
            'type_units.name as unit_type_name',
            'forms.title as form_title',
            'users.name as user_name',
            'locations.name as location_name',
            DB::raw("DATE_FORMAT(dailies.date, '%d-%m-%Y %H:%i:%s') as date"),
            DB::raw("CONCAT('Shift - ', shifts.name) as shift_name"),

            DB::raw('(
                    SELECT COUNT(*)
                    FROM detail_dailies
                    JOIN status ON status.id = detail_dailies.status_id
                    WHERE detail_dailies.dailies_id = dailies.id
                    AND status.name LIKE "%rusak%"
                ) as rusak_count'),

            DB::raw('(
                    CASE
                        WHEN (
                            SELECT COUNT(*)
                            FROM detail_dailies
                            JOIN status ON status.id = detail_dailies.status_id
                            WHERE detail_dailies.dailies_id = dailies.id
                            AND status.name LIKE "%rusak%"
                        ) > 0
                        THEN "Ada Yang Rusak"
                        ELSE "Completed"
                    END
                ) as status_checklist'),
        ])
            ->join('forms', 'forms.id', '=', 'dailies.form_id')
            ->join('users', 'users.id', '=', 'dailies.user_id')
            ->join('locations', 'locations.id', '=', 'dailies.location_id')
            ->join('shifts', 'shifts.id', '=', 'dailies.shift_id')
            ->join('units', 'units.id', '=', 'dailies.unit_id')
            ->join('type_units', 'type_units.id', '=', 'units.type_id')
            ->when($sitesId, fn($q) => $q->where('dailies.location_id', $sitesId))
            ->when($shiftId, fn($q) => $q->where('dailies.shift_id', $shiftId))
            ->when($date, fn($q) => $q->whereDate('dailies.date', $date))
            ->when(!$allAccess, function ($rw) {
                $rw->where("dailies.location_id", auth()->user()->location_id);
            })
            ->whereHas('location', function ($q) {
                $q->whereNull('deleted_at');
            })
            ->when($search, function ($q) use ($search) {
                $q->where(function ($query) use ($search) {
                    $query->where('dailies.code_report', 'like', "%{$search}%")
                        ->orWhere('units.unit_code', 'like', "%{$search}%")
                        ->orWhere('type_units.name', 'like', "%{$search}%")
                        ->orWhere('forms.title', 'like', "%{$search}%")
                        ->orWhere('users.name', 'like', "%{$search}%");
                });
            })
            ->orderBy('dailies.id', 'desc');
        $isDriverOperator = in_array(strtolower(auth()->user()->role->role), ["driver", "operator"]);

        // if (!$allAccess && $userId !== null) {
        //     $query->where('dailies.user_id', $userId);
        // }
        if ($isDriverOperator) {
            $query->where('dailies.user_id', $userId);
        }

        return $query->filterByRole()->get();
    }

    public function getUnit($id, $locationId = null)
    {
        $unitypeId = Form::where('id', $id)->value('type_unit_id');

        $query = Unit::where('type_id', $unitypeId);

        if ($locationId !== null) {
            $query->where('location_id', $locationId);
        }

        return $query->get();
    }

    public function createDailyWithDetails($data)
    {
        $daily = DB::transaction(function () use ($data) {

            $unit = Unit::findOrFail($data["unit_id"]);
            $location = Location::findOrFail($data['location_id']);
            $shift = Shift::findOrFail($data["shift_id"]);

            $code_report = 'do_' . now()->format('Ymd') . '_' .
                str_replace(' ', '_', $location->name) . '_' .
                $unit->unit_code . '_' .
                $shift->name . '_' .
                str_replace(' ', '_', auth()->user()->name);

            $daily = Daily::create([
                'form_id' => $data['form_id'],
                'user_id' => $data['user_id'],
                'shift_id' => $data['shift_id'],
                'location_id' => $data['location_id'],
                'unit_id' => $data['unit_id'],
                'code_report' => $code_report,
                'date' => now(),
                'status_daily' => $data['status_daily'] ?? 'pending',
                'comment' => $data['comment'] ?? null
            ]);

            foreach ($data['details'] as $detail) {
                DetailDaily::create([
                    'dailies_id' => $daily->id,
                    'unit_id' => $detail['unit_id'],
                    'form_item_id' => $detail['form_item_id'],
                    'status_id' => $detail['status_id'],
                    'note' => $detail['note'] ?? null,
                ]);
            }

            DB::afterCommit(function () use ($daily, $location, $shift, $unit) {
                try {

                    $this->generatePdf($daily, $location, $shift, $unit);
                    $daily->update(["status_daily" => "completed"]);

                    Log::info("✅ PDF dan status berhasil dibuat untuk daily_id={$daily->id}");
                } catch (\Exception $e) {
                    Log::error("❌ Gagal generate PDF untuk daily_id={$daily->id}: " . $e->getMessage());
                }
            });

            return $daily;
        });

        return $daily->load('detail');
    }



    private function generatePdf($daily, $location, $shift, $unit)
    {
        try {
            $daily_item = DetailDaily::where('dailies_id', $daily->id)->latest()->get();
            $status = Status::all();

            $year = now()->format('Y');
            $month = now()->format('m');
            $locationName = str_replace(" ", "_", $location->name);

            $folderPath = public_path("PDF_PMM/{$year}/{$month}/{$locationName}/{$shift->name}");

            if (!File::exists($folderPath)) {
                File::makeDirectory($folderPath, 0777, true, true);
            }

            $status = Status::all();
            $fileName = "{$daily->code_report}.pdf";
            $filePath = "{$folderPath}/{$fileName}";

            $pdf = Pdf::loadView('daily.pdf.index', [
                'daily' => $daily,
                'unit' => $unit,
                'location' => $location,
                'shift' => $shift,
                'daily_item' => $daily_item,
                'status' => $status,
                'user' => auth()->user(),
            ]);

            $pdf->save($filePath);
            $publicUrl = asset("{$filePath}");

            return $publicUrl;
        } catch (\Exception $e) {
            Log::error("❌ Error generate PDF untuk daily_id={$daily->id}: " . $e->getMessage());
            throw $e;
        }
    }

    public function deleteDailyWithDetails($id)
    {
        $daily = Daily::where('id', $id)->first();

        DetailDaily::where('dailies_id', $daily->id)->delete();

        $daily->delete();

        return true;
    }


}
