<?php
namespace Crawl\Services;

class IssueService
{
    public function summarize(array $pages): array
    {
        $issues = [
            'TITLE_MISSING'        => ['severity' => 'high',     'label' => 'Missing title',                  'count' => 0, 'sample_urls' => []],
            'TITLE_TOO_LONG'       => ['severity' => 'medium',   'label' => 'Title too long (>60 chars)',     'count' => 0, 'sample_urls' => []],
            'TITLE_TOO_SHORT'      => ['severity' => 'low',      'label' => 'Title too short (<30 chars)',    'count' => 0, 'sample_urls' => []],
            'TITLE_DUPLICATE'      => ['severity' => 'high',     'label' => 'Duplicate title tag',            'count' => 0, 'sample_urls' => []],
            'META_DESC_MISSING'    => ['severity' => 'medium',   'label' => 'Missing meta description',       'count' => 0, 'sample_urls' => []],
            'META_DESC_TOO_LONG'   => ['severity' => 'low',      'label' => 'Meta description too long (>160)', 'count' => 0, 'sample_urls' => []],
            'META_DESC_TOO_SHORT'  => ['severity' => 'low',      'label' => 'Meta description too short (<70)', 'count' => 0, 'sample_urls' => []],
            'META_DESC_DUPLICATE'  => ['severity' => 'medium',   'label' => 'Duplicate meta description',     'count' => 0, 'sample_urls' => []],
            'H1_MISSING'           => ['severity' => 'medium',   'label' => 'Missing H1',                     'count' => 0, 'sample_urls' => []],
            'H1_MULTIPLE'          => ['severity' => 'medium',   'label' => 'Multiple H1 tags',               'count' => 0, 'sample_urls' => []],
            'STATUS_4XX_5XX'       => ['severity' => 'critical',  'label' => 'Client/Server errors',          'count' => 0, 'sample_urls' => []],
            'REDIRECT_3XX'         => ['severity' => 'medium',   'label' => 'Redirect pages (3xx)',           'count' => 0, 'sample_urls' => []],
            'NOINDEX'              => ['severity' => 'high',     'label' => 'Noindex pages',                  'count' => 0, 'sample_urls' => []],
            'THIN_CONTENT'         => ['severity' => 'medium',   'label' => 'Thin content (<300 words)',      'count' => 0, 'sample_urls' => []],
            'DUPLICATE_CONTENT'    => ['severity' => 'high',     'label' => 'Duplicate content',             'count' => 0, 'sample_urls' => []],
            'CANONICAL_MISSING'    => ['severity' => 'low',      'label' => 'Missing canonical tag',          'count' => 0, 'sample_urls' => []],
            'CANONICAL_MISMATCH'   => ['severity' => 'medium',   'label' => 'Non-self canonical (review)',    'count' => 0, 'sample_urls' => []],
            'SLOW_PAGE'            => ['severity' => 'medium',   'label' => 'Slow page (>3s response)',       'count' => 0, 'sample_urls' => []],
            'LOW_READABILITY'      => ['severity' => 'medium',   'label' => 'Low readability (Flesch <50)',   'count' => 0, 'sample_urls' => []],
        ];

        // Pre-pass: count hash duplicates, title duplicates, meta duplicates
        $hashCount  = [];
        $titleCount = [];
        $metaCount  = [];

        foreach ($pages as $page) {
            $hash = (string)($page['content_hash'] ?? '');
            if ($hash !== '') $hashCount[$hash] = ($hashCount[$hash] ?? 0) + 1;

            $title = trim(strtolower((string)($page['title'] ?? '')));
            if ($title !== '') $titleCount[$title] = ($titleCount[$title] ?? 0) + 1;

            $meta = trim(strtolower((string)($page['meta_description'] ?? '')));
            if ($meta !== '') $metaCount[$meta] = ($metaCount[$meta] ?? 0) + 1;
        }

        foreach ($pages as $page) {
            $url    = $page['url'];
            $status = (int)($page['status_code'] ?? 0);

            // Only audit indexable HTML pages for content checks
            $robots  = strtolower((string)($page['meta_robots'] ?? '')) . ' ' . strtolower((string)($page['x_robots_tag'] ?? ''));
            $noindex = str_contains($robots, 'noindex');
            $isHtml  = str_contains(strtolower((string)($page['content_type'] ?? '')), 'html');

            // Status checks
            if ($status >= 500) $this->pushIssue($issues['STATUS_4XX_5XX'], $url);
            elseif ($status >= 400) $this->pushIssue($issues['STATUS_4XX_5XX'], $url);
            elseif ($status >= 300) $this->pushIssue($issues['REDIRECT_3XX'], $url);

            if ($noindex) $this->pushIssue($issues['NOINDEX'], $url);

            if ((float)($page['response_time'] ?? 0) > 3.0) {
                $this->pushIssue($issues['SLOW_PAGE'], $url);
            }

            $flesch = (float)($page['flesch_reading_ease'] ?? 0);
            if ($flesch > 0 && $flesch < 50 && $status === 200 && $isHtml) {
                $this->pushIssue($issues['LOW_READABILITY'], $url);
            }

            // Skip content checks for non-200 or non-HTML
            if ($status !== 200 || !$isHtml) continue;

            // Title checks
            $titleText = (string)($page['title'] ?? '');
            $titleLen  = (int)($page['title_length'] ?? strlen($titleText));
            if ($titleText === '') {
                $this->pushIssue($issues['TITLE_MISSING'], $url);
            } else {
                if ($titleLen > 60)  $this->pushIssue($issues['TITLE_TOO_LONG'],  $url);
                if ($titleLen < 30)  $this->pushIssue($issues['TITLE_TOO_SHORT'], $url);
                $titleKey = trim(strtolower($titleText));
                if (($titleCount[$titleKey] ?? 0) > 1) $this->pushIssue($issues['TITLE_DUPLICATE'], $url);
            }

            // Meta description checks
            $metaText = (string)($page['meta_description'] ?? '');
            $metaLen  = (int)($page['meta_description_length'] ?? strlen($metaText));
            if ($metaText === '') {
                $this->pushIssue($issues['META_DESC_MISSING'], $url);
            } else {
                if ($metaLen > 160) $this->pushIssue($issues['META_DESC_TOO_LONG'],  $url);
                if ($metaLen < 70)  $this->pushIssue($issues['META_DESC_TOO_SHORT'], $url);
                $metaKey = trim(strtolower($metaText));
                if (($metaCount[$metaKey] ?? 0) > 1) $this->pushIssue($issues['META_DESC_DUPLICATE'], $url);
            }

            // H1 checks
            $h1 = (string)($page['h1'] ?? '');
            if ($h1 === '') {
                $this->pushIssue($issues['H1_MISSING'], $url);
            } else {
                // Multiple H1: h2_list stores h2s, but the crawler stores single h1 string.
                // If HtmlParser stored multiple h1s concatenated in h1 field, we detect via count.
                // Simple heuristic: if h1 contains a newline or pipe it's likely multiple.
                if (substr_count($h1, "\n") >= 1 || substr_count($h1, ' | ') >= 1) {
                    $this->pushIssue($issues['H1_MULTIPLE'], $url);
                }
            }

            // Canonical checks
            $canonical = (string)($page['canonical_url'] ?? '');
            if ($canonical === '') {
                $this->pushIssue($issues['CANONICAL_MISSING'], $url);
            } elseif (rtrim($canonical, '/') !== rtrim($url, '/')) {
                $this->pushIssue($issues['CANONICAL_MISMATCH'], $url);
            }

            // Content checks
            $wc = (int)($page['word_count'] ?? 0);
            if ($wc > 0 && $wc < 300) $this->pushIssue($issues['THIN_CONTENT'], $url);

            $hash = (string)($page['content_hash'] ?? '');
            if ($hash !== '' && ($hashCount[$hash] ?? 0) > 1) {
                $this->pushIssue($issues['DUPLICATE_CONTENT'], $url);
            }
        }

        return array_values(array_filter($issues, static fn(array $item): bool => $item['count'] > 0));
    }

    /**
     * Detect image-level issues from crawl_images rows.
     * Call separately from summarize() and merge results.
     */
    public function summarizeImages(array $imageRows, array $pages): array
    {
        // Build a set of page URLs that have at least one missing-alt image
        $pagesWithMissingAlt = [];
        foreach ($imageRows as $img) {
            if ($img['is_missing_alt']) {
                $pagesWithMissingAlt[$img['page_url']] = true;
            }
        }
        if (empty($pagesWithMissingAlt)) return [];

        // Only flag pages that are indexable 200 HTML pages
        $indexableHtmlUrls = [];
        foreach ($pages as $p) {
            if ((int)($p['status_code'] ?? 0) === 200 &&
                str_contains(strtolower((string)($p['content_type'] ?? '')), 'html')) {
                $indexableHtmlUrls[$p['url']] = true;
            }
        }

        $count   = count(array_intersect_key($pagesWithMissingAlt, $indexableHtmlUrls));
        $samples = array_slice(array_keys(array_intersect_key($pagesWithMissingAlt, $indexableHtmlUrls)), 0, 5);
        if ($count === 0) return [];

        return [[
            'severity'    => 'low',
            'label'       => 'Images missing alt text',
            'count'       => $count,
            'sample_urls' => $samples,
        ]];
    }

    /**
     * Compute a 0-100 health score from summarized issues.
     * Weights: critical=15, high=8, medium=4, low=1 per affected page (capped at 100 deduction).
     */
    public function healthScore(array $issueSummary, int $totalPages): int
    {
        if ($totalPages === 0) return 100;

        $weights  = ['critical' => 15, 'high' => 8, 'medium' => 4, 'low' => 1];
        $deduction = 0;

        foreach ($issueSummary as $issue) {
            $w          = $weights[$issue['severity']] ?? 1;
            $ratio      = min(1.0, $issue['count'] / $totalPages);
            $deduction += $w * $ratio * 10;
        }

        return max(0, (int)round(100 - min(100, $deduction)));
    }

    private function pushIssue(array &$issue, string $url): void
    {
        $issue['count']++;
        if (count($issue['sample_urls']) < 5) {
            $issue['sample_urls'][] = $url;
        }
    }
}
