<?php
namespace Crawl\Repositories;

use Crawl\Lib\Database;

class OAuthTokenRepository
{
    private Database $db;

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

    public function find(int $projectId, string $service): ?array
    {
        // Project-specific token first
        $row = $this->findExact($projectId, $service);
        if ($row) return $row;

        // Fall back to global account token (project_id = 0)
        if ($projectId !== 0) {
            return $this->db->fetch(
                'SELECT * FROM project_oauth_tokens WHERE project_id = 0 AND service = ?',
                [$service]
            );
        }
        return null;
    }

    public function allForProject(int $projectId): array
    {
        return $this->db->fetchAll(
            'SELECT service, account_email, property_id, token_expires_at, updated_at
             FROM project_oauth_tokens WHERE project_id = ?',
            [$projectId]
        );
    }

    // Returns map: ['ga4' => [...], 'gsc' => [...], 'gbp' => [...]] for a project
    public function statusForProject(int $projectId): array
    {
        $map = [];
        foreach (['ga4', 'gsc', 'gbp'] as $service) {
            $row = $this->find($projectId, $service);
            if (!$row) continue;
            $map[$service] = [
                'service'          => $service,
                'account_email'    => $row['account_email'] ?? null,
                'property_id'      => $row['property_id'] ?? null,
                'token_expires_at' => $row['token_expires_at'] ?? null,
                'updated_at'       => $row['updated_at'] ?? null,
                'project_id'       => (int)($row['project_id'] ?? $projectId),
                'is_global'        => (int)($row['project_id'] ?? $projectId) === 0,
            ];
        }
        return $map;
    }

    // Returns service → bool connected map for multiple projects at once
    public function connectedMap(array $projectIds): array
    {
        if (empty($projectIds)) return [];
        $ph   = implode(',', array_fill(0, count($projectIds), '?'));
        $rows = $this->db->fetchAll(
            "SELECT project_id, service, account_email FROM project_oauth_tokens WHERE project_id IN ({$ph})",
            $projectIds
        );
        $map  = [];
        foreach ($rows as $row) {
            $map[(int)$row['project_id']][$row['service']] = $row['account_email'];
        }
        return $map;
    }

    public function upsert(int $projectId, string $service, array $data): void
    {
        $existing = $this->findExact($projectId, $service);
        $now      = date('Y-m-d H:i:s');

        if ($existing) {
            $this->db->update('project_oauth_tokens', array_merge($data, ['updated_at' => $now]),
                'project_id = :project_id AND service = :service',
                ['project_id' => $projectId, 'service' => $service]
            );
        } else {
            $this->db->insert('project_oauth_tokens', array_merge([
                'project_id' => $projectId,
                'service'    => $service,
                'created_at' => $now,
                'updated_at' => $now,
            ], $data));
        }
    }

    public function delete(int $projectId, string $service): void
    {
        $this->db->query(
            'DELETE FROM project_oauth_tokens WHERE project_id = ? AND service = ?',
            [$projectId, $service]
        );
    }

    private function findExact(int $projectId, string $service): ?array
    {
        return $this->db->fetch(
            'SELECT * FROM project_oauth_tokens WHERE project_id = ? AND service = ?',
            [$projectId, $service]
        );
    }
}
