<?php

declare(strict_types=1);

namespace App\Repositories;

use App\Database;
use PDO;

final class AdminRepository
{
    private PDO $db;

    public function __construct()
    {
        $this->db = Database::connection();
    }

    public function dashboardCounts(): array
    {
        return [
            'posts' => (int) $this->db->query("SELECT COUNT(*) FROM posts WHERE deleted_at IS NULL")->fetchColumn(),
            'published' => (int) $this->db->query("SELECT COUNT(*) FROM posts WHERE status = 'published' AND deleted_at IS NULL")->fetchColumn(),
            'inquiries' => (int) $this->db->query("SELECT COUNT(*) FROM inquiries WHERE deleted_at IS NULL")->fetchColumn(),
            'pending' => (int) $this->db->query("SELECT COUNT(*) FROM inquiries WHERE status IN ('pending','in_progress') AND deleted_at IS NULL")->fetchColumn(),
        ];
    }

    public function adminCount(): int
    {
        return (int) $this->db->query('SELECT COUNT(*) FROM admins')->fetchColumn();
    }

    public function createAdmin(string $username, string $displayName, string $password): void
    {
        $statement = $this->db->prepare(
            'INSERT INTO admins (username, password_hash, display_name)
             VALUES (:username, :password_hash, :display_name)'
        );
        $statement->execute([
            'username' => $username,
            'password_hash' => password_hash($password, PASSWORD_DEFAULT),
            'display_name' => $displayName,
        ]);
    }

    public function posts(): array
    {
        return $this->db->query(
            "SELECT id, title, slug, category, status, published_at, updated_at
             FROM posts WHERE deleted_at IS NULL ORDER BY created_at DESC LIMIT 100"
        )->fetchAll();
    }

    public function inquiries(): array
    {
        return $this->db->query(
            "SELECT id, ticket, name, phone, inquiry_type, title, status, created_at
             FROM inquiries WHERE deleted_at IS NULL ORDER BY created_at DESC LIMIT 100"
        )->fetchAll();
    }

    public function findPost(int $id): ?array
    {
        $statement = $this->db->prepare(
            'SELECT posts.*,
                (SELECT file_path FROM post_images WHERE post_id = posts.id ORDER BY sort_order, id LIMIT 1) AS image_path,
                (SELECT alt_text FROM post_images WHERE post_id = posts.id ORDER BY sort_order, id LIMIT 1) AS image_alt
             FROM posts WHERE posts.id = :id AND posts.deleted_at IS NULL LIMIT 1'
        );
        $statement->execute(['id' => $id]);
        $post = $statement->fetch();
        return $post ?: null;
    }

    public function savePost(array $data, ?int $id = null): int
    {
        $publishedAt = $data['status'] === 'published'
            ? ($data['published_at'] ?: date('Y-m-d H:i:s'))
            : null;

        if ($id === null) {
            $statement = $this->db->prepare(
                'INSERT INTO posts (title, slug, category, excerpt, body, author, status, published_at)
                 VALUES (:title, :slug, :category, :excerpt, :body, :author, :status, :published_at)'
            );
            $statement->execute([
                'title'=>$data['title'],'slug'=>$data['slug'],'category'=>$data['category'],
                'excerpt'=>$data['excerpt'],'body'=>$data['body'],'author'=>$data['author'],
                'status'=>$data['status'],'published_at'=>$publishedAt,
            ]);
            return (int) $this->db->lastInsertId();
        }

        $statement = $this->db->prepare(
            'UPDATE posts SET title=:title, slug=:slug, category=:category, excerpt=:excerpt,
             body=:body, author=:author, status=:status, published_at=:published_at WHERE id=:id AND deleted_at IS NULL'
        );
        $statement->execute([
            'title'=>$data['title'],'slug'=>$data['slug'],'category'=>$data['category'],
            'excerpt'=>$data['excerpt'],'body'=>$data['body'],'author'=>$data['author'],
            'status'=>$data['status'],'published_at'=>$publishedAt,'id'=>$id,
        ]);
        return $id;
    }

    public function savePostWithImage(array $data, ?int $id, ?string $imagePath, string $imageAlt): array
    {
        $oldPaths = [];
        $this->db->beginTransaction();
        try {
            $postId = $this->savePost($data, $id);
            if ($imagePath !== null) {
                $select = $this->db->prepare('SELECT file_path FROM post_images WHERE post_id = :post_id FOR UPDATE');
                $select->execute(['post_id' => $postId]);
                $oldPaths = array_column($select->fetchAll(), 'file_path');

                $delete = $this->db->prepare('DELETE FROM post_images WHERE post_id = :post_id');
                $delete->execute(['post_id' => $postId]);
                $insert = $this->db->prepare(
                    'INSERT INTO post_images (post_id, file_path, alt_text, sort_order)
                     VALUES (:post_id, :file_path, :alt_text, 0)'
                );
                $insert->execute(['post_id'=>$postId, 'file_path'=>$imagePath, 'alt_text'=>$imageAlt]);
            } elseif ($id !== null) {
                $update = $this->db->prepare(
                    'UPDATE post_images SET alt_text = :alt_text WHERE post_id = :post_id AND sort_order = 0'
                );
                $update->execute(['post_id'=>$postId, 'alt_text'=>$imageAlt]);
            }
            $this->db->commit();
            return ['id' => $postId, 'old_paths' => $oldPaths];
        } catch (\Throwable $exception) {
            if ($this->db->inTransaction()) {
                $this->db->rollBack();
            }
            throw $exception;
        }
    }

    public function slugExists(string $slug, ?int $exceptId = null): bool
    {
        $sql = 'SELECT COUNT(*) FROM posts WHERE slug = :slug AND deleted_at IS NULL';
        $params = ['slug' => $slug];
        if ($exceptId !== null) {
            $sql .= ' AND id <> :id';
            $params['id'] = $exceptId;
        }
        $statement = $this->db->prepare($sql);
        $statement->execute($params);
        return (int) $statement->fetchColumn() > 0;
    }

    public function deletePost(int $id): void
    {
        $statement = $this->db->prepare('UPDATE posts SET deleted_at = NOW() WHERE id = :id');
        $statement->execute(['id' => $id]);
    }

    public function findInquiry(int $id): ?array
    {
        $statement = $this->db->prepare('SELECT * FROM inquiries WHERE id = :id AND deleted_at IS NULL LIMIT 1');
        $statement->execute(['id' => $id]);
        $inquiry = $statement->fetch();
        return $inquiry ?: null;
    }

    public function updateInquiry(int $id, string $status, string $reply): void
    {
        $statement = $this->db->prepare(
            'UPDATE inquiries SET status = :new_status, reply = :reply,
             replied_at = CASE WHEN :has_reply = 1 THEN NOW() ELSE replied_at END,
             closed_at = CASE
               WHEN :closed_status = \'closed\' AND closed_at IS NULL THEN NOW()
               WHEN :open_status <> \'closed\' THEN NULL
               ELSE closed_at
             END
             WHERE id = :id AND deleted_at IS NULL'
        );
        $statement->execute([
            'new_status' => $status,
            'closed_status' => $status,
            'open_status' => $status,
            'reply' => $reply === '' ? null : $reply,
            'has_reply' => $reply === '' ? 0 : 1,
            'id' => $id,
        ]);
    }
}
