import { useEffect, useState, useRef } from 'react';
import { Card, Row, Col, Statistic, Table, Button, Typography, Spin, Grid, App, theme } from 'antd';
import type { ColumnsType } from 'antd/es/table';
import { EyeOutlined, EyeInvisibleOutlined } from '@ant-design/icons';
import { MapContainer, TileLayer, Polyline, CircleMarker, useMap } from 'react-leaflet';
import type { Map as LeafletMap } from 'leaflet';
import 'leaflet/dist/leaflet.css';
import dayjs from 'dayjs';
import duration from 'dayjs/plugin/duration';
import { api } from '@/lib/api';
import type { TrackingSessionSummary, SessionRoute, TrackPointEvent } from '@/types/tracking';
import type { PaginationMeta } from '@/types/api';

dayjs.extend(duration);

const EVENT_COLORS: Record<TrackPointEvent, string> = {
  SESSION_STARTED: '#52c41a',
  SESSION_ENDED: '#ff4d4f',
  VISIT_RECORDED: '#1890ff',
  LOCATION_ADDED: '#fa8c16',
};

const EVENT_LABELS: Record<TrackPointEvent, string> = {
  SESSION_STARTED: 'Start',
  SESSION_ENDED: 'End',
  VISIT_RECORDED: 'Visit',
  LOCATION_ADDED: 'Location Added',
};

function FitBounds({ coordinates }: { coordinates: [number, number][] }) {
  const map = useMap();
  useEffect(() => {
    if (coordinates.length > 0) {
      const bounds = coordinates.map((c) => [c[0], c[1]] as [number, number]);
      map.fitBounds(bounds, { padding: [30, 30] });
    }
  }, [coordinates, map]);
  return null;
}

function formatDuration(startedAt: string, endedAt: string | null): string {
  if (!endedAt) return 'Active';
  const dur = dayjs.duration(dayjs(endedAt).diff(dayjs(startedAt)));
  const h = Math.floor(dur.asHours());
  const m = dur.minutes();
  if (h > 0) return `${h}h ${m}m`;
  return `${m}m`;
}

function formatDistance(meters: number): string {
  if (meters >= 1000) return `${(meters / 1000).toFixed(1)} km`;
  return `${Math.round(meters)} m`;
}

export default function MyRoutesPage() {
  const { message } = App.useApp();
  const screens = Grid.useBreakpoint();
  const isMobile = !screens.md;
  const { token } = theme.useToken();

  const [sessions, setSessions] = useState<TrackingSessionSummary[]>([]);
  const [pagination, setPagination] = useState<PaginationMeta | null>(null);
  const [loading, setLoading] = useState(true);
  const [page, setPage] = useState(1);

  const [selectedId, setSelectedId] = useState<string | null>(null);
  const [route, setRoute] = useState<SessionRoute | null>(null);
  const [routeLoading, setRouteLoading] = useState(false);

  const mapRef = useRef<LeafletMap | null>(null);

  useEffect(() => {
    const load = async () => {
      setLoading(true);
      try {
        const { data } = await api.get('/map/tracking/my/sessions', {
          params: { page, limit: 15 },
        });
        setSessions(data.sessions);
        setPagination(data.pagination);
      } catch {
        message.error('Failed to load routes');
      } finally {
        setLoading(false);
      }
    };
    load();
  }, [page]); // eslint-disable-line react-hooks/exhaustive-deps

  const handleView = async (sessionId: string) => {
    if (selectedId === sessionId) {
      setSelectedId(null);
      setRoute(null);
      return;
    }

    setSelectedId(sessionId);
    setRouteLoading(true);
    try {
      const { data } = await api.get(`/map/tracking/my/sessions/${sessionId}/route`);
      setRoute(data);
    } catch {
      message.error('Failed to load route');
      setSelectedId(null);
    } finally {
      setRouteLoading(false);
    }
  };

  // Aggregate stats
  const totalSessions = pagination?.total ?? 0;
  const totalDistance = sessions.reduce((sum, s) => sum + s.totalDistanceM, 0);
  const totalTime = sessions.reduce((sum, s) => {
    if (!s.endedAt) return sum;
    return sum + dayjs(s.endedAt).diff(dayjs(s.startedAt), 'minute');
  }, 0);

  const columns: ColumnsType<TrackingSessionSummary> = [
    {
      title: 'Date',
      dataIndex: 'startedAt',
      key: 'startedAt',
      render: (val: string) => dayjs(val).format('MMM D, h:mm A'),
    },
    {
      title: 'Duration',
      key: 'duration',
      render: (_: unknown, r: TrackingSessionSummary) => formatDuration(r.startedAt, r.endedAt),
    },
    {
      title: 'Distance',
      dataIndex: 'totalDistanceM',
      key: 'distance',
      render: (val: number) => formatDistance(val),
    },
    {
      title: 'Points',
      dataIndex: 'totalPoints',
      key: 'points',
      responsive: ['md'] as any,
    },
    {
      title: '',
      key: 'actions',
      width: 80,
      render: (_: unknown, r: TrackingSessionSummary) => (
        <Button
          type={selectedId === r.id ? 'primary' : 'text'}
          icon={selectedId === r.id ? <EyeInvisibleOutlined /> : <EyeOutlined />}
          size="small"
          loading={routeLoading && selectedId === r.id}
          onClick={() => handleView(r.id)}
        >
          {isMobile ? '' : selectedId === r.id ? 'Hide' : 'View'}
        </Button>
      ),
    },
  ];

  if (loading && sessions.length === 0) {
    return <div style={{ textAlign: 'center', padding: 48 }}><Spin size="large" /></div>;
  }

  return (
    <div>
      <Typography.Title level={3} style={{ marginBottom: 16 }}>My Routes</Typography.Title>

      <Row gutter={[12, 12]} style={{ marginBottom: 24 }}>
        <Col xs={8}>
          <Card size="small"><Statistic title="Sessions" value={totalSessions} /></Card>
        </Col>
        <Col xs={8}>
          <Card size="small"><Statistic title="Distance" value={formatDistance(totalDistance)} /></Card>
        </Col>
        <Col xs={8}>
          <Card size="small"><Statistic title="Time" value={totalTime > 60 ? `${Math.floor(totalTime / 60)}h ${totalTime % 60}m` : `${totalTime}m`} /></Card>
        </Col>
      </Row>

      {/* Map */}
      <Card
        size="small"
        style={{ marginBottom: 24, overflow: 'hidden' }}
        styles={{ body: { padding: 0 } }}
      >
        <div style={{ height: 300 }}>
          <MapContainer
            center={[45.42, -75.69]}
            zoom={12}
            style={{ height: '100%', width: '100%' }}
            ref={mapRef}
          >
            <TileLayer
              attribution='&copy; <a href="https://carto.com">CARTO</a>'
              url="https://{s}.basemaps.cartocdn.com/dark_all/{z}/{x}/{y}{r}.png"
            />
            {route && route.coordinates.length > 0 && (
              <>
                <Polyline
                  positions={route.coordinates}
                  pathOptions={{ color: token.colorPrimary, weight: 3, opacity: 0.8 }}
                />
                {route.events.map((evt, i) => (
                  <CircleMarker
                    key={i}
                    center={[evt.latitude, evt.longitude]}
                    radius={6}
                    pathOptions={{
                      color: EVENT_COLORS[evt.eventType],
                      fillColor: EVENT_COLORS[evt.eventType],
                      fillOpacity: 0.9,
                      weight: 2,
                    }}
                  >
                  </CircleMarker>
                ))}
                <FitBounds coordinates={route.coordinates} />
              </>
            )}
            {!route && (
              <div
                style={{
                  position: 'absolute',
                  top: '50%',
                  left: '50%',
                  transform: 'translate(-50%, -50%)',
                  zIndex: 1000,
                  color: 'rgba(255,255,255,0.5)',
                  fontSize: 14,
                  textAlign: 'center',
                  pointerEvents: 'none',
                }}
              >
                Select a session to view its route
              </div>
            )}
          </MapContainer>
        </div>
      </Card>

      {/* Legend */}
      {route && (
        <div style={{ display: 'flex', gap: 16, marginBottom: 16, flexWrap: 'wrap' }}>
          {Object.entries(EVENT_COLORS).map(([key, color]) => (
            <div key={key} style={{ display: 'flex', alignItems: 'center', gap: 4 }}>
              <div style={{ width: 10, height: 10, borderRadius: '50%', background: color }} />
              <Typography.Text type="secondary" style={{ fontSize: 12 }}>
                {EVENT_LABELS[key as TrackPointEvent]}
              </Typography.Text>
            </div>
          ))}
        </div>
      )}

      <Card title="Sessions" size="small">
        <Table
          dataSource={sessions}
          columns={columns}
          rowKey="id"
          size="small"
          scroll={isMobile ? { x: 400 } : undefined}
          loading={loading}
          pagination={{
            current: page,
            total: pagination?.total ?? 0,
            pageSize: 15,
            showSizeChanger: false,
            onChange: setPage,
          }}
        />
      </Card>
    </div>
  );
}
