<?php
declare(strict_types=1);

namespace App\Repositories;

use App\Support\GoogleCalendar;

final class HearingRepository extends BaseRepository
{
    private const HEARING_TYPES = [
        'hazirliq', 'baxis', 'ilkin_baxis', 'akt_elani', 'mumkunluk', 'erize_baxis', 'yerli_baxis',
    ];

    public function create(array $data): int
    {
        $ownerUserId = $this->ownerUserId();
        $caseId = (int)$data['is_id'];
        $caseCheck = $this->db->prepare(
            'SELECT
                (SELECT COUNT(*) FROM mehkeme_ishleri WHERE id=? AND owner_user_id=?) +
                (SELECT COUNT(*) FROM mehkeme_arxiv WHERE id=? AND owner_user_id=?)'
        );
        $caseCheck->execute([$caseId, $ownerUserId, $caseId, $ownerUserId]);
        if ((int)$caseCheck->fetchColumn() < 1) {
            throw new \InvalidArgumentException('Court case is not available');
        }

        $date = \DateTimeImmutable::createFromFormat('!Y-m-d', trim((string)$data['tarix']));
        if (!$date || $date->format('Y-m-d') !== trim((string)$data['tarix'])) {
            throw new \InvalidArgumentException('Hearing date is invalid');
        }
        $timeInput = trim((string)$data['saat']);
        if (preg_match('/^(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d)?$/', $timeInput) !== 1) {
            throw new \InvalidArgumentException('Hearing time is invalid');
        }
        $time = substr($timeInput, 0, 5);
        $hearingType = trim((string)($data['iclas_novu'] ?? ''));
        if ($hearingType !== '' && !in_array($hearingType, self::HEARING_TYPES, true)) {
            throw new \InvalidArgumentException('Hearing type is invalid');
        }

        $stmt = $this->db->prepare(
            'INSERT INTO iclaslar (is_id, tarix, saat, iclas_novu, veziyyet, qeydler, gcal_event_id, istirak_edildi, owner_user_id)
             VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)'
        );
        $stmt->execute([
            $caseId,
            $date->format('Y-m-d'),
            $time,
            $hearingType !== '' ? $hearingType : null,
            $data['veziyyet'] ?? 'quvvededir',
            $data['qeydler'] ?? '',
            ($data['gcal_event_id'] ?? '') ?: null,
            !empty($data['istirak_edildi']) ? 1 : 0,
            $ownerUserId,
        ]);

        $this->db->prepare(
            'UPDATE mehkeme_ishleri SET qeyri_mueyyen_texir=0 WHERE id=? AND owner_user_id=?'
        )->execute([$caseId, $ownerUserId]);

        $hearingId = (int)$this->db->lastInsertId();
        try {
            (new GoogleCalendar($this->db, $ownerUserId))->syncHearing($hearingId);
        } catch (\Throwable $exception) {
            error_log('Google Calendar API hearing sync failed: ' . $exception->getMessage());
        }
        return $hearingId;
    }

    public function between(string $start, string $end): array
    {
        $stmt = $this->db->prepare(
            "SELECT i.*,
                    COALESCE(m.is_nomresi, a.is_nomresi) AS is_nomresi,
                    COALESCE(m.terefin_adi, a.terefin_adi) AS terefin_adi,
                    COALESCE(m.mehkemenin_adi, a.mehkemenin_adi) AS mehkemenin_adi,
                    COALESCE(m.hakimin_adi, a.hakimin_adi) AS hakimin_adi
             FROM iclaslar i
             LEFT JOIN mehkeme_ishleri m ON i.is_id = m.id AND m.owner_user_id=i.owner_user_id
             LEFT JOIN mehkeme_arxiv a ON i.is_id = a.id AND a.owner_user_id=i.owner_user_id AND m.id IS NULL
             WHERE i.owner_user_id=? AND i.tarix BETWEEN ? AND ? AND i.veziyyet = 'quvvededir'
             ORDER BY i.tarix ASC, i.saat ASC, i.id ASC"
        );
        $stmt->execute([$this->ownerUserId(), $start, $end]);
        return $stmt->fetchAll();
    }

    public function listForBot(): array
    {
        $stmt = $this->db->prepare(
            "SELECT i.*,
                    COALESCE(m.is_nomresi, a.is_nomresi) AS is_nomresi,
                    COALESCE(m.terefin_adi, a.terefin_adi) AS terefin_adi,
                    COALESCE(m.mehkemenin_adi, a.mehkemenin_adi) AS mehkemenin_adi,
                    COALESCE(m.hakimin_adi, a.hakimin_adi) AS hakimin_adi
             FROM iclaslar i
             LEFT JOIN mehkeme_ishleri m ON i.is_id=m.id AND m.owner_user_id=i.owner_user_id
             LEFT JOIN mehkeme_arxiv a ON i.is_id=a.id AND a.owner_user_id=i.owner_user_id AND m.id IS NULL
             WHERE i.owner_user_id=?
               AND i.tarix BETWEEN DATE_SUB(CURDATE(), INTERVAL 30 DAY)
                               AND DATE_ADD(CURDATE(), INTERVAL 5 YEAR)
             ORDER BY
               CASE WHEN CONCAT(i.tarix, ' ', LEFT(i.saat, 5)) >= NOW() THEN 0 ELSE 1 END,
               CASE WHEN CONCAT(i.tarix, ' ', LEFT(i.saat, 5)) >= NOW()
                    THEN CONCAT(i.tarix, ' ', LEFT(i.saat, 5)) END ASC,
               CASE WHEN CONCAT(i.tarix, ' ', LEFT(i.saat, 5)) < NOW()
                    THEN CONCAT(i.tarix, ' ', LEFT(i.saat, 5)) END DESC,
               i.id DESC
             LIMIT 150"
        );
        $stmt->execute([$this->ownerUserId()]);
        return $stmt->fetchAll();
    }

    public function findForBot(int $id): ?array
    {
        $stmt = $this->db->prepare(
            "SELECT i.*,
                    COALESCE(m.is_nomresi, a.is_nomresi) AS is_nomresi,
                    COALESCE(m.terefin_adi, a.terefin_adi) AS terefin_adi,
                    COALESCE(m.mehkemenin_adi, a.mehkemenin_adi) AS mehkemenin_adi,
                    COALESCE(m.hakimin_adi, a.hakimin_adi) AS hakimin_adi
             FROM iclaslar i
             LEFT JOIN mehkeme_ishleri m ON i.is_id=m.id AND m.owner_user_id=i.owner_user_id
             LEFT JOIN mehkeme_arxiv a ON i.is_id=a.id AND a.owner_user_id=i.owner_user_id AND m.id IS NULL
             WHERE i.id=? AND i.owner_user_id=?
             LIMIT 1"
        );
        $stmt->execute([$id, $this->ownerUserId()]);
        $row = $stmt->fetch();
        return $row ?: null;
    }

    public function patchFromBot(int $id, string $field, mixed $value): array
    {
        if ($this->findForBot($id) === null) {
            throw new \InvalidArgumentException('İclas tapılmadı');
        }

        if ($field === 'datetime') {
            $normalized = trim((string)$value);
            $dateTime = \DateTimeImmutable::createFromFormat('!Y-m-d H:i', $normalized);
            if (!$dateTime || $dateTime->format('Y-m-d H:i') !== $normalized) {
                throw new \InvalidArgumentException('İclasın tarix və saatı düzgün deyil');
            }
            $this->db->prepare(
                'UPDATE iclaslar SET tarix=?, saat=? WHERE id=? AND owner_user_id=?'
            )->execute([
                $dateTime->format('Y-m-d'),
                $dateTime->format('H:i'),
                $id,
                $this->ownerUserId(),
            ]);
        } elseif ($field === 'type') {
            $hearingType = trim((string)$value);
            if (!in_array($hearingType, self::HEARING_TYPES, true)) {
                throw new \InvalidArgumentException('İclasın növü düzgün deyil');
            }
            $this->db->prepare(
                'UPDATE iclaslar SET iclas_novu=? WHERE id=? AND owner_user_id=?'
            )->execute([$hearingType, $id, $this->ownerUserId()]);
        } else {
            throw new \InvalidArgumentException('Dəyişdirilən iclas sahəsi düzgün deyil');
        }

        $this->syncGoogleCalendar($id);
        return $this->findForBot($id) ?? [];
    }

    public function setStatusFromBot(int $id, string $status): array
    {
        $hearing = $this->findForBot($id);
        if ($hearing === null) {
            throw new \InvalidArgumentException('İclas tapılmadı');
        }
        if (!in_array($status, ['legv_edildi', 'istirak_edildi', 'istirak_edilmedi'], true)) {
            throw new \InvalidArgumentException('İclas nəticəsi düzgün deyil');
        }

        if (in_array($status, ['istirak_edildi', 'istirak_edilmedi'], true)) {
            $scheduledAt = \DateTimeImmutable::createFromFormat(
                '!Y-m-d H:i',
                (string)$hearing['tarix'] . ' ' . substr((string)$hearing['saat'], 0, 5)
            );
            if (!$scheduledAt || $scheduledAt > new \DateTimeImmutable('now')) {
                throw new \InvalidArgumentException('İştirak nəticəsi yalnız iclasın vaxtı çatdıqdan sonra seçilə bilər');
            }
        }

        $state = $status === 'legv_edildi' ? 'legv_edildi' : 'quvvededir';
        $result = $status === 'legv_edildi' ? 'gozlemede' : $status;
        $attended = $status === 'istirak_edildi' ? 1 : 0;
        $this->db->prepare(
            'UPDATE iclaslar
             SET veziyyet=?, iclas_neticesi=?, istirak_edildi=?
             WHERE id=? AND owner_user_id=?'
        )->execute([$state, $result, $attended, $id, $this->ownerUserId()]);

        $this->syncGoogleCalendar($id);
        return $this->findForBot($id) ?? [];
    }

    private function syncGoogleCalendar(int $hearingId): void
    {
        try {
            (new GoogleCalendar($this->db, $this->ownerUserId()))->syncHearing($hearingId);
        } catch (\Throwable $exception) {
            error_log('Google Calendar API hearing sync failed: ' . $exception->getMessage());
        }
    }
}
