<?php

namespace App\Livewire\PaketPekerjaan;

use App\Models\PaketPekerjaan;
use App\Models\OPD;
use App\Models\BadanUsaha;
use App\Models\TenagaAhli;
use Livewire\Component;
use Livewire\Attributes\Rule;
use Livewire\Attributes\On;
use Illuminate\Validation\Rule as ValidationRule;

class Form extends Component
{
    public $showModal = false;

    #[Rule('required|string|max:50|unique:paket_pekerjaans,kode_paket')]
    public $kode_paket = '';

    #[Rule('required|string|max:255')]
    public $nama_paket = '';

    #[Rule('nullable|numeric|min:0')]
    public $nilai_total = '';

    #[Rule('required|in:perencanaan,tender,progres,selesai')]
    public $status = 'perencanaan';

    #[Rule('nullable|date')]
    public $kontrak_mulai = '';

    #[Rule('nullable|date|after_or_equal:kontrak_mulai')]
    public $kontrak_selesai = '';

    #[Rule('required|exists:opds,id')]
    public $opd_id = '';

    #[Rule('required|exists:badan_usaha,id')]
    public $badan_usaha_id = '';

    #[Rule('required|array|min:1')]
    public $tenaga_ahli_ids = [];

    public $editingId = null;

    #[On('form-show')]
    public function show($paketPekerjaanId = null)
    {
        $this->resetForm();
        $this->showModal = true;

        if ($paketPekerjaanId) {
            $this->editingId = $paketPekerjaanId;
            $paketPekerjaan = PaketPekerjaan::with(['opd', 'badanUsaha', 'tenagaAhli'])->find($paketPekerjaanId);

            $this->kode_paket = $paketPekerjaan->kode_paket;
            $this->nama_paket = $paketPekerjaan->nama_paket;
            $this->nilai_total = $paketPekerjaan->nilai_total;
            $this->status = $paketPekerjaan->status;
            $this->kontrak_mulai = $paketPekerjaan->kontrak_mulai;
            $this->kontrak_selesai = $paketPekerjaan->kontrak_selesai;
            $this->opd_id = $paketPekerjaan->opd_id;
            $this->badan_usaha_id = $paketPekerjaan->badan_usaha_id;
            $this->tenaga_ahli_ids = $paketPekerjaan->tenagaAhli->pluck('id')->toArray();
        }
    }

    public function save()
    {
        // Validasi dasar
        $this->validate();

        // Validasi custom untuk OPD
        $this->validateOpdPaketLimit();

        // Validasi custom untuk Tenaga Ahli
        $this->validateTenagaAhliAvailability();

        $data = [
            'kode_paket' => $this->kode_paket,
            'nama_paket' => $this->nama_paket,
            'nilai_total' => $this->nilai_total ?: null,
            'status' => $this->status,
            'kontrak_mulai' => $this->kontrak_mulai ?: null,
            'kontrak_selesai' => $this->kontrak_selesai ?: null,
            'opd_id' => $this->opd_id,
            'badan_usaha_id' => $this->badan_usaha_id,
        ];

        if ($this->editingId) {
            $paketPekerjaan = PaketPekerjaan::find($this->editingId);
            $paketPekerjaan->update($data);
            $paketPekerjaan->tenagaAhli()->sync($this->tenaga_ahli_ids);
        } else {
            $paketPekerjaan = PaketPekerjaan::create($data);
            $paketPekerjaan->tenagaAhli()->attach($this->tenaga_ahli_ids);
        }

        $this->dispatch('item-saved');
        $this->closeModal();
    }

    private function validateOpdPaketLimit()
    {
        // Jika tidak ada tanggal kontrak, skip validasi ini
        if (!$this->kontrak_mulai || !$this->kontrak_selesai) {
            return;
        }

        $kontrakMulai = \Carbon\Carbon::parse($this->kontrak_mulai);
        $kontrakSelesai = \Carbon\Carbon::parse($this->kontrak_selesai);

        // Cari paket pekerjaan yang tumpang tindih dengan periode kontrak ini
        $overlappingPakets = PaketPekerjaan::where('opd_id', $this->opd_id)
            ->where('id', '!=', $this->editingId) // Exclude current record if editing
            ->where(function ($query) use ($kontrakMulai, $kontrakSelesai) {
                $query->where(function ($q) use ($kontrakMulai, $kontrakSelesai) {
                    // Paket yang dimulai sebelum periode ini dan selesai setelah periode ini dimulai
                    $q->where('kontrak_mulai', '<=', $kontrakMulai)
                      ->where('kontrak_selesai', '>=', $kontrakMulai);
                })->orWhere(function ($q) use ($kontrakMulai, $kontrakSelesai) {
                    // Paket yang dimulai dalam periode ini
                    $q->where('kontrak_mulai', '>=', $kontrakMulai)
                      ->where('kontrak_mulai', '<=', $kontrakSelesai);
                })->orWhere(function ($q) use ($kontrakMulai, $kontrakSelesai) {
                    // Paket yang selesai dalam periode ini
                    $q->where('kontrak_selesai', '>=', $kontrakMulai)
                      ->where('kontrak_selesai', '<=', $kontrakSelesai);
                });
            })
            ->count();

        if ($overlappingPakets >= 5) {
            $this->addError('opd_id', 'OPD ini sudah memiliki 5 paket pekerjaan yang tumpang tindih dengan periode kontrak yang dipilih. Maksimal hanya 5 paket pekerjaan yang dapat berjalan bersamaan.');
        }
    }

    private function validateTenagaAhliAvailability()
    {
        foreach ($this->tenaga_ahli_ids as $tenagaAhliId) {
            // Cari paket pekerjaan aktif yang menggunakan tenaga ahli ini
            $activePakets = PaketPekerjaan::whereHas('tenagaAhli', function ($query) use ($tenagaAhliId) {
                $query->where('tenaga_ahli_id', $tenagaAhliId);
            })
            ->where('id', '!=', $this->editingId) // Exclude current record if editing
            ->where('status', '!=', 'selesai') // Exclude completed projects
            ->where(function ($query) {
                // Jika ada tanggal kontrak, cek apakah masih aktif
                if ($this->kontrak_mulai && $this->kontrak_selesai) {
                    $kontrakMulai = \Carbon\Carbon::parse($this->kontrak_mulai);
                    $kontrakSelesai = \Carbon\Carbon::parse($this->kontrak_selesai);

                    $query->where(function ($q) use ($kontrakMulai, $kontrakSelesai) {
                        $q->where(function ($subQ) use ($kontrakMulai, $kontrakSelesai) {
                            $subQ->where('kontrak_mulai', '<=', $kontrakSelesai)
                                 ->where('kontrak_selesai', '>=', $kontrakMulai);
                        });
                    });
                } else {
                    // Jika tidak ada tanggal kontrak, cek semua paket non-selesai
                    $query->whereNull('kontrak_selesai')
                          ->orWhere('kontrak_selesai', '>=', now());
                }
            })
            ->get();

            if ($activePakets->count() > 0) {
                $tenagaAhli = TenagaAhli::find($tenagaAhliId);
                $paketNames = $activePakets->pluck('nama_paket')->implode(', ');
                $this->addError('tenaga_ahli_ids', "Tenaga Ahli '{$tenagaAhli->nama_tenaga_ahli}' sudah terlibat dalam paket pekerjaan aktif: {$paketNames}. Satu tenaga ahli hanya dapat terlibat dalam satu paket pekerjaan aktif pada waktu yang sama.");
            }
        }
    }

    public function updatedKontrakMulai()
    {
        $this->validateKontrakDates();
    }

    public function updatedKontrakSelesai()
    {
        $this->validateKontrakDates();
    }

    public function updatedOpdId()
    {
        $this->validateOpdPaketLimit();
    }

    private function validateKontrakDates()
    {
        if ($this->kontrak_mulai && $this->kontrak_selesai) {
            $kontrakMulai = \Carbon\Carbon::parse($this->kontrak_mulai);
            $kontrakSelesai = \Carbon\Carbon::parse($this->kontrak_selesai);

            if ($kontrakSelesai <= $kontrakMulai) {
                $this->addError('kontrak_selesai', 'Tanggal kontrak selesai harus setelah tanggal kontrak mulai.');
            }
        }
    }

    public function resetForm()
    {
        $this->reset([
            'kode_paket', 'nama_paket', 'nilai_total', 'status', 'kontrak_mulai',
            'kontrak_selesai', 'opd_id', 'badan_usaha_id', 'tenaga_ahli_ids', 'editingId'
        ]);
        $this->status = 'perencanaan';
    }

    public function closeModal()
    {
        $this->showModal = false;
        $this->resetForm();
    }

    public function render()
    {
        $tenagaAhlis = TenagaAhli::all()->map(function ($tenagaAhli) {
            $tenagaAhli->is_available = $this->isTenagaAhliAvailable($tenagaAhli->id);
            return $tenagaAhli;
        });

        return view('livewire.paket-pekerjaan.form', [
            'statusList' => PaketPekerjaan::STATUS_LIST,
            'opds' => OPD::where('status', 'aktif')->get(),
            'badanUsahas' => BadanUsaha::all(),
            'tenagaAhlis' => $tenagaAhlis,
        ]);
    }

    private function isTenagaAhliAvailable($tenagaAhliId)
    {
        // Cari paket pekerjaan aktif yang menggunakan tenaga ahli ini
        $activePakets = PaketPekerjaan::whereHas('tenagaAhli', function ($query) use ($tenagaAhliId) {
            $query->where('tenaga_ahli_id', $tenagaAhliId);
        })
        ->where('id', '!=', $this->editingId) // Exclude current record if editing
        ->where('status', '!=', 'selesai') // Exclude completed projects
        ->where(function ($query) {
            // Jika ada tanggal kontrak, cek apakah masih aktif
            if ($this->kontrak_mulai && $this->kontrak_selesai) {
                $kontrakMulai = \Carbon\Carbon::parse($this->kontrak_mulai);
                $kontrakSelesai = \Carbon\Carbon::parse($this->kontrak_selesai);

                $query->where(function ($q) use ($kontrakMulai, $kontrakSelesai) {
                    $q->where(function ($subQ) use ($kontrakMulai, $kontrakSelesai) {
                        $subQ->where('kontrak_mulai', '<=', $kontrakSelesai)
                             ->where('kontrak_selesai', '>=', $kontrakMulai);
                    });
                });
            } else {
                // Jika tidak ada tanggal kontrak, cek semua paket non-selesai
                $query->whereNull('kontrak_selesai')
                      ->orWhere('kontrak_selesai', '>=', now());
            }
        })
        ->get();

        return $activePakets->count() === 0;
    }
}
