import { useState, useEffect, useCallback, useMemo } from 'react';
import { Row, Col, Card, Table, Select, Button, App, Spin, Empty } from 'antd';
import {
  ReloadOutlined,
  GlobalOutlined,
} from '@ant-design/icons';
import { MapContainer, TileLayer, CircleMarker, Popup } from 'react-leaflet';
import 'leaflet/dist/leaflet.css';
import { useOutletContext } from 'react-router-dom';
import { api } from '@/lib/api';
import type { AppOutletContext } from '@/types/api';

/* ------------------------------------------------------------------ */
/*  Types                                                              */
/* ------------------------------------------------------------------ */

interface CountryRow {
  country: string;
  views: number;
}

interface CityRow {
  city: string;
  region: string | null;
  country: string;
  views: number;
}

interface GeoPoint {
  latitude: number;
  longitude: number;
  count: number;
  module: string;
}

interface GeoData {
  viewsByCountry: CountryRow[];
  topCities: CityRow[];
  geoPoints: GeoPoint[];
}

/* ------------------------------------------------------------------ */
/*  Constants                                                          */
/* ------------------------------------------------------------------ */

const MODULE_COLORS: Record<string, string> = {
  docs: '#1890ff',
  video: '#722ed1',
  photo: '#52c41a',
};

const MODULE_LABELS: Record<string, string> = {
  docs: 'Docs',
  video: 'Video',
  photo: 'Photo',
};

function markerRadius(count: number): number {
  return Math.max(5, Math.min(20, Math.sqrt(count) * 3));
}

/* ------------------------------------------------------------------ */
/*  Table columns                                                      */
/* ------------------------------------------------------------------ */

function buildCountryColumns(totalViews: number) {
  return [
    {
      title: 'Country',
      dataIndex: 'country',
      key: 'country',
      width: 100,
    },
    {
      title: 'Views',
      dataIndex: 'views',
      key: 'views',
      width: 90,
      sorter: (a: CountryRow, b: CountryRow) => a.views - b.views,
      defaultSortOrder: 'descend' as const,
    },
    {
      title: '% of Total',
      key: 'pct',
      width: 100,
      render: (_: unknown, row: CountryRow) => {
        const pct = totalViews > 0 ? ((row.views / totalViews) * 100).toFixed(1) : '0.0';
        return `${pct}%`;
      },
    },
  ];
}

const cityColumns = [
  {
    title: 'City',
    dataIndex: 'city',
    key: 'city',
    ellipsis: true,
  },
  {
    title: 'Region',
    dataIndex: 'region',
    key: 'region',
    width: 110,
    ellipsis: true,
    render: (v: string | null) => v ?? '\u2014',
  },
  {
    title: 'Country',
    dataIndex: 'country',
    key: 'country',
    width: 80,
  },
  {
    title: 'Views',
    dataIndex: 'views',
    key: 'views',
    width: 80,
    sorter: (a: CityRow, b: CityRow) => a.views - b.views,
    defaultSortOrder: 'descend' as const,
  },
];

/* ------------------------------------------------------------------ */
/*  Component                                                          */
/* ------------------------------------------------------------------ */

export default function GeoAnalyticsPage() {
  const { setPageHeader } = useOutletContext<AppOutletContext>();
  const [days, setDays] = useState(30);
  const [data, setData] = useState<GeoData | null>(null);
  const [loading, setLoading] = useState(true);
  const { message } = App.useApp();

  useEffect(() => {
    setPageHeader({ title: 'Geographic Analytics' });
    return () => setPageHeader(null);
  }, [setPageHeader]);

  const fetchData = useCallback(async () => {
    setLoading(true);
    try {
      const res = await api.get('/analytics/geo', { params: { days } });
      setData(res.data);
    } catch {
      message.error('Failed to load geographic analytics');
    } finally {
      setLoading(false);
    }
  }, [days, message]);

  useEffect(() => {
    fetchData();
  }, [fetchData]);

  const totalViews = useMemo(
    () => (data ? data.viewsByCountry.reduce((s, r) => s + r.views, 0) : 0),
    [data],
  );

  const countryColumns = useMemo(() => buildCountryColumns(totalViews), [totalViews]);

  return (
    <div>
      {/* Header row */}
      <div style={{ display: 'flex', alignItems: 'center', gap: 12, marginBottom: 24 }}>
        <GlobalOutlined style={{ fontSize: 18 }} />
        <div style={{ flex: 1 }} />
        <Select
          value={days}
          onChange={setDays}
          style={{ width: 140 }}
          options={[
            { label: 'Last 7 days', value: 7 },
            { label: 'Last 30 days', value: 30 },
            { label: 'Last 90 days', value: 90 },
            { label: 'Last 365 days', value: 365 },
          ]}
        />
        <Button icon={<ReloadOutlined />} onClick={fetchData} loading={loading}>
          Refresh
        </Button>
      </div>

      {loading && !data ? (
        <div style={{ textAlign: 'center', padding: 80 }}>
          <Spin size="large" />
        </div>
      ) : !data ? (
        <Empty description="No geographic data available" />
      ) : (
        <>
          {/* Map */}
          <Card title="Visitor Locations" style={{ marginBottom: 24 }}>
            {data.geoPoints.length === 0 ? (
              <Empty description="No location data for this period" />
            ) : (
              <div style={{ height: 400, width: '100%' }}>
                <MapContainer
                  center={[30, 0]}
                  zoom={2}
                  style={{ height: '100%', width: '100%', borderRadius: 8 }}
                  scrollWheelZoom
                >
                  <TileLayer
                    attribution='&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a>'
                    url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
                  />
                  {data.geoPoints.map((pt, idx) => (
                    <CircleMarker
                      key={`${pt.latitude}-${pt.longitude}-${pt.module}-${idx}`}
                      center={[pt.latitude, pt.longitude]}
                      radius={markerRadius(pt.count)}
                      pathOptions={{
                        color: MODULE_COLORS[pt.module] ?? '#1890ff',
                        fillColor: MODULE_COLORS[pt.module] ?? '#1890ff',
                        fillOpacity: 0.55,
                        weight: 1,
                      }}
                    >
                      <Popup>
                        <div style={{ fontSize: 12 }}>
                          <strong>{MODULE_LABELS[pt.module] ?? pt.module}</strong>
                          <br />
                          {pt.count.toLocaleString()} view{pt.count !== 1 ? 's' : ''}
                        </div>
                      </Popup>
                    </CircleMarker>
                  ))}
                </MapContainer>
              </div>
            )}

            {/* Map legend */}
            {data.geoPoints.length > 0 && (
              <div style={{ display: 'flex', gap: 16, marginTop: 12, fontSize: 12 }}>
                {Object.entries(MODULE_COLORS).map(([mod, color]) => (
                  <span key={mod} style={{ display: 'flex', alignItems: 'center', gap: 4 }}>
                    <span
                      style={{
                        display: 'inline-block',
                        width: 10,
                        height: 10,
                        borderRadius: '50%',
                        background: color,
                      }}
                    />
                    {MODULE_LABELS[mod] ?? mod}
                  </span>
                ))}
              </div>
            )}
          </Card>

          {/* Two tables side by side */}
          <Row gutter={[16, 16]}>
            <Col xs={24} md={12}>
              <Card title="Views by Country">
                {data.viewsByCountry.length === 0 ? (
                  <Empty description="No country data" />
                ) : (
                  <Table
                    dataSource={data.viewsByCountry}
                    columns={countryColumns}
                    rowKey="country"
                    pagination={{ pageSize: 10, showSizeChanger: false }}
                    size="small"
                    scroll={{ x: 280 }}
                  />
                )}
              </Card>
            </Col>
            <Col xs={24} md={12}>
              <Card title="Top Cities">
                {data.topCities.length === 0 ? (
                  <Empty description="No city data" />
                ) : (
                  <Table
                    dataSource={data.topCities}
                    columns={cityColumns}
                    rowKey={(r, i) => `${r.city}-${r.country}-${i}`}
                    pagination={{ pageSize: 10, showSizeChanger: false }}
                    size="small"
                    scroll={{ x: 350 }}
                  />
                )}
              </Card>
            </Col>
          </Row>
        </>
      )}
    </div>
  );
}
