<?php

declare(strict_types=1);

namespace SeoScope\Repositories;

use PDO;

final class SyncLogRepository
{
    public function __construct(
        private PDO $pdo,
        private string $tablePrefix
    ) {}

    private function runsTable(): string
    {
        return '`' . str_replace('`', '``', $this->tablePrefix . 'sync_runs') . '`';
    }

    private function itemsTable(): string
    {
        return '`' . str_replace('`', '``', $this->tablePrefix . 'sync_run_items') . '`';
    }

    public function startRun(string $mode, string $rangeStart, string $rangeEnd): int
    {
        $t = $this->runsTable();
        $stmt = $this->pdo->prepare(
            "INSERT INTO {$t} (started_at, status, mode, range_start, range_end)
             VALUES (?, 'running', ?, ?, ?)"
        );
        $stmt->execute([date('Y-m-d H:i:s'), $mode, $rangeStart, $rangeEnd]);
        return (int) $this->pdo->lastInsertId();
    }

    public function finishRun(
        int $runId,
        string $status,
        int $propertiesTotal,
        int $propertiesFailed,
        int $daysProcessed,
        int $queryUpserts,
        int $pageUpserts,
        ?string $errorSummary
    ): void {
        $t = $this->runsTable();
        $stmt = $this->pdo->prepare(
            "UPDATE {$t}
             SET finished_at = ?, status = ?, properties_total = ?, properties_failed = ?,
                 days_processed = ?, query_upserts = ?, page_upserts = ?, error_summary = ?
             WHERE id = ? LIMIT 1"
        );
        $stmt->execute([
            date('Y-m-d H:i:s'),
            $status,
            $propertiesTotal,
            $propertiesFailed,
            $daysProcessed,
            $queryUpserts,
            $pageUpserts,
            $errorSummary,
            $runId,
        ]);
    }

    public function startItem(int $runId, ?int $propertyId, string $siteUrl, string $fromDate, string $toDate): int
    {
        $t = $this->itemsTable();
        $cols = "run_id, site_url, from_date, to_date, status, started_at";
        $vals = "?, ?, ?, ?, 'running', ?";
        $args = [$runId, $siteUrl, $fromDate, $toDate, date('Y-m-d H:i:s')];
        if ($propertyId !== null) {
            $cols = "run_id, property_id, site_url, from_date, to_date, status, started_at";
            $vals = "?, ?, ?, ?, ?, 'running', ?";
            $args = [$runId, $propertyId, $siteUrl, $fromDate, $toDate, date('Y-m-d H:i:s')];
        }
        $stmt = $this->pdo->prepare("INSERT INTO {$t} ({$cols}) VALUES ({$vals})");
        $stmt->execute($args);
        return (int) $this->pdo->lastInsertId();
    }

    public function finishItem(
        int $itemId,
        string $status,
        int $daysProcessed,
        int $queryUpserts,
        int $pageUpserts,
        ?string $errorSummary
    ): void {
        $t = $this->itemsTable();
        $stmt = $this->pdo->prepare(
            "UPDATE {$t}
             SET finished_at = ?, status = ?, days_processed = ?, query_upserts = ?, page_upserts = ?, error_summary = ?
             WHERE id = ? LIMIT 1"
        );
        $stmt->execute([
            date('Y-m-d H:i:s'),
            $status,
            $daysProcessed,
            $queryUpserts,
            $pageUpserts,
            $errorSummary,
            $itemId,
        ]);
    }

    /**
     * @return list<array<string,mixed>>
     */
    public function recentRuns(int $limit = 10): array
    {
        $t = $this->runsTable();
        $limit = max(1, min(50, $limit));
        $stmt = $this->pdo->query(
            "SELECT id, started_at, finished_at, status, mode, range_start, range_end,
                    properties_total, properties_failed, days_processed, query_upserts, page_upserts, error_summary
             FROM {$t}
             ORDER BY id DESC
             LIMIT {$limit}"
        );
        $rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
        return is_array($rows) ? $rows : [];
    }

    /**
     * @return list<array<string,mixed>>
     */
    public function recentItems(int $limit = 20): array
    {
        $t = $this->itemsTable();
        $limit = max(1, min(100, $limit));
        $stmt = $this->pdo->query(
            "SELECT run_id, site_url, from_date, to_date, status, days_processed, query_upserts, page_upserts, error_summary, started_at, finished_at
             FROM {$t}
             ORDER BY id DESC
             LIMIT {$limit}"
        );
        $rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
        return is_array($rows) ? $rows : [];
    }
}

