import { Download, Map, PlugZap } from 'lucide-react';

import { useEffect, useState, useRef } from 'react';

import { Head, Link, router, usePage } from '@inertiajs/react';

import { UpgradePrompt } from '@/Components/billing/UpgradePrompt';
import PageHeader from '@/Components/layout/PageHeader';
import SiteNav from '@/Components/Navigation/SiteNav';
import OpportunityFilters from '@/Components/OpportunityMap/OpportunityFilters';
import UnifiedCard from '@/Components/OpportunityMap/UnifiedCard';
import InertiaPagination from '@/Components/Shared/InertiaPagination';
import { Button } from '@/Components/ui/button';
import { EmptyState } from '@/Components/ui/empty-state';
import { useNavigationState } from '@/hooks/useNavigationState';
import { useSiteKeyboardShortcuts } from '@/hooks/useSiteKeyboardShortcuts';
import DashboardLayout from '@/Layouts/DashboardLayout';
import { trackEvent, trackFilterApplied } from '@/lib/analytics';
import { OPPORTUNITY_MAP_VIEWED } from '@/lib/event-catalog';
import type { PageProps, PaginatedResponse, SiteBasic } from '@/types';

interface Demand {
  clicks_before?: number;
  clicks_after?: number;
  delta_percent?: number;
  days_declining?: number;
  query_cluster?: string;
  competing_pages?: number;
  total_clicks?: number;
  volatility?: number;
  cluster_name?: string;
  cluster_demand?: number;
  coverage_percentage?: number;
  missing_entity?: string;
}

interface Opportunity {
  opportunity_type:
    | 'recommendation'
    | 'freshness'
    | 'cannibalization'
    | 'topic_gap'
    | 'keyword_opportunity';
  opportunity_id: number;
  page_url: string;
  demand: Demand | null;
  issue: string;
  action: string;
  confidence: number;
  impact_score: number;
  reasoning: string;
  evidence?: Record<string, unknown>;
  status?: string;
  lifecycle_status?: string;
  keyword_opportunity_type?: 'striking_distance' | 'ctr_gap' | 'rising_query' | 'content_gap';
}

interface Props {
  site: SiteBasic;
  opportunities: PaginatedResponse<Opportunity>;
  filters: {
    type: string | null;
    sort: string | null;
    min_confidence: number | null;
    min_impact: number | null;
  };
  counts: Record<string, number>;
}

export default function OpportunityMapIndex({ site, opportunities, filters, counts }: Props) {
  const page = usePage<PageProps>();
  const { limits } = page.props;
  const sites = Array.isArray(page.props.sites) ? page.props.sites : [];
  const siteSummary = sites.find((s) => s.id === site.id);
  const hasGsc = siteSummary?.has_gsc ?? true;

  useEffect(() => {
    trackEvent(OPPORTUNITY_MAP_VIEWED, { site_id: String(site.id), feature: 'opportunity_map' });
  }, [site.id]);

  // Track opportunity_type filter changes (applied via Link navigation).
  // The mountFiredRef guard prevents double-tracking in React strict mode,
  // which double-invokes effects on mount in development.
  const prevTypeRef = useRef<string | null | undefined>(undefined);
  const mountFiredRef = useRef(false);
  useEffect(() => {
    const isMount = prevTypeRef.current === undefined;
    if (isMount && filters.type) {
      if (!mountFiredRef.current) {
        mountFiredRef.current = true;
        trackFilterApplied('opportunity_type', filters.type);
      }
    } else if (!isMount && filters.type !== prevTypeRef.current) {
      trackFilterApplied('opportunity_type', filters.type ?? 'cleared');
    }
    prevTypeRef.current = filters.type ?? null;
  }, [filters.type]);

  const [confidenceThreshold, setConfidenceThreshold] = useState(filters.min_confidence ?? 0);
  const [impactThreshold, setImpactThreshold] = useState(filters.min_impact ?? 0);
  const [sortBy, setSortBy] = useState(filters.sort ?? 'impact_desc');
  const filtersRef = useRef<HTMLDivElement>(null);
  const isNavigating = useNavigationState();

  useSiteKeyboardShortcuts({
    onSearch: () => filtersRef.current?.focus(),
  });

  // Debounced filter updates
  useEffect(() => {
    const timer = setTimeout(() => {
      const params = new URLSearchParams();
      if (filters.type) params.set('type', filters.type);
      if (confidenceThreshold > 0) params.set('min_confidence', String(confidenceThreshold));
      if (impactThreshold > 0) params.set('min_impact', String(impactThreshold));
      if (sortBy) params.set('sort', sortBy);

      const newUrl =
        route('opportunity-map.index', { site: site.id }) +
        (params.toString() ? '?' + params.toString() : '');

      // Only reload if filters changed
      if (
        filters.min_confidence !== confidenceThreshold ||
        filters.min_impact !== impactThreshold ||
        filters.sort !== sortBy
      ) {
        if (filters.min_confidence !== confidenceThreshold) {
          trackFilterApplied('min_confidence', String(confidenceThreshold));
        }
        if (filters.min_impact !== impactThreshold) {
          trackFilterApplied('min_impact', String(impactThreshold));
        }
        if (filters.sort !== sortBy) {
          trackFilterApplied('sort', sortBy);
        }
        router.visit(newUrl, { preserveState: true, preserveScroll: true });
      }
    }, 300);

    return () => clearTimeout(timer);
  }, [confidenceThreshold, impactThreshold, sortBy, site.id, filters]);

  const hasOpportunities = counts.total > 0;

  return (
    <>
      <Head title={`${site.name} - Opportunity Map`} />

      <PageHeader
        title="Opportunity Map"
        subtitle="All opportunities in one unified view"
        actions={
          <>
            <Button variant="outline" asChild>
              <Link
                href={route('opportunity-map.export', {
                  site: site.id,
                  type: filters.type,
                  sort: filters.sort,
                  min_confidence: filters.min_confidence,
                  min_impact: filters.min_impact,
                })}
                as="a"
              >
                <Download className="h-4 w-4 mr-2" aria-hidden="true" />
                Export CSV
              </Link>
            </Button>
            <Button variant="outline" asChild>
              <Link href={route('sites.settings.analysis.show', site.id)}>Settings</Link>
            </Button>
          </>
        }
      />

      <div className="container py-6">
        <SiteNav
          siteId={site.id}
          canAnalyze
          canRecommend
          canCannibalization
          canOpportunityMap
          canGeographic
          canDevice
        />

        {!hasOpportunities && !hasGsc && (
          <EmptyState
            icon={PlugZap}
            title="Connect Google Search Console first"
            description="The Opportunity Map shows keyword opportunities, traffic trends, content gaps, and more — all in one place. Connect GSC to start surfacing data for your site."
            action={
              <Button asChild>
                <Link href={route('sites.settings.show', site.id)}>Connect Google Search Console</Link>
              </Button>
            }
            secondaryAction={
              <p className="text-xs text-muted-foreground">
                GSC data powers striking-distance keywords, CTR gap detection, rising queries, and cannibalization analysis.
              </p>
            }
          />
        )}

        {!hasOpportunities && hasGsc && (
          <EmptyState
            icon={Map}
            title="No opportunities discovered yet"
            description="The Opportunity Map aggregates insights from recommendations, content freshness, keyword analysis, and cannibalization detection. Run at least one analysis to populate this view."
            action={
              <div className="flex flex-wrap gap-2 justify-center">
                <Button asChild>
                  <Link href={route('analyze.index', site.id)}>Run Analysis</Link>
                </Button>
                <Button variant="outline" asChild>
                  <Link href={route('freshness.index', site.id)}>Check Content Freshness</Link>
                </Button>
              </div>
            }
            secondaryAction={
              <p className="text-xs text-muted-foreground">
                After your first analysis, opportunities appear here automatically.
              </p>
            }
          />
        )}

        {/* BILL-003: Upgrade prompt when at free tier limits */}
        {limits && limits.max_sites_per_user <= 1 && hasOpportunities && (
          <div className="mb-4">
            <UpgradePrompt
              limitType="pages"
              currentUsage={limits.max_sites_per_user}
              maxUsage={limits.max_sites_per_user}
              proLimit="Unlimited"
              ctaLabel="Unlock All Keyword Opportunities"
              customMessage="Upgrade to unlock full opportunity map access with unlimited analysis."
            />
          </div>
        )}

        {hasOpportunities && (
          <>
            {/* Filters */}
            <div ref={filtersRef} tabIndex={-1} className="mb-6 rounded-lg border bg-card p-4 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2">
              <OpportunityFilters
                counts={counts}
                currentFilter={filters.type}
                siteId={site.id}
                confidenceThreshold={confidenceThreshold}
                impactThreshold={impactThreshold}
                sortBy={sortBy}
                currentFilters={filters}
                onConfidenceChange={setConfidenceThreshold}
                onImpactChange={setImpactThreshold}
                onSortChange={setSortBy}
              />
            </div>

            {/* Result Count */}
            <div className="mb-4 flex items-center justify-between">
              <p className="text-sm text-muted-foreground">
                Showing{' '}
                <strong>
                  {opportunities.from ?? 0}–{opportunities.to ?? 0}
                </strong>{' '}
                of <strong>{counts.total}</strong> opportunities
              </p>
            </div>

            {/* Opportunity Cards */}
            <div className={`space-y-4 transition-opacity ${isNavigating ? 'opacity-50' : ''}`}>
              {opportunities.data.length === 0 ? (
                <EmptyState
                  title="No opportunities match your filters"
                  description="Try adjusting your confidence or impact thresholds, or change the opportunity type filter."
                  action={
                    <Button variant="outline" asChild>
                      <Link href={route('opportunity-map.index', site.id)}>Clear All Filters</Link>
                    </Button>
                  }
                />
              ) : (
                opportunities.data.map((opportunity) => (
                  <UnifiedCard
                    key={`${opportunity.opportunity_type}-${opportunity.opportunity_id}`}
                    opportunity={opportunity}
                    siteId={site.id}
                  />
                ))
              )}
            </div>

            <InertiaPagination
              links={opportunities.links}
              currentPage={opportunities.current_page}
              lastPage={opportunities.last_page}
              perPage={opportunities.per_page}
              total={opportunities.total}
            />
          </>
        )}
      </div>
    </>
  );
}

OpportunityMapIndex.layout = (page: React.ReactElement) => <DashboardLayout children={page} />;
