import React, { useCallback, useEffect, useState } from "react";
import styled from "styled-components";
import {
  DriveConnectIntent,
  DriveConnectionKind,
  DriveConnectionType,
  DriveProvider,
  connectDrive,
  disconnectDriveConnection,
  driveSyncProgressPercent,
  fetchDriveConnections,
  formatDriveSyncError,
  parseResourceIdsInput,
  saveDriveResourceSelection,
  syncDriveConnection,
  waitForDriveSyncSettlement,
} from "../../utils/drive";

const Section = styled.div`
  background: ${({ theme }) => theme.colors.cardBackground};
  backdrop-filter: blur(10px);
  border: 1px solid ${({ theme }) => theme.colors.cardBorder};
  border-radius: 1rem;
  padding: 2rem;
  width: 100%;
  max-width: 1000px;
  margin-bottom: 2rem;
  box-shadow: 0 8px 32px 0 rgba(0, 0, 0, 0.37);
`;

const SectionTitle = styled.h2`
  font-size: 1.8rem;
  margin-bottom: 0.5rem;
  color: ${({ theme }) => theme.colors.text};
  border-bottom: 1px solid ${({ theme }) => theme.colors.cardBorder};
  padding-bottom: 1rem;
`;

const SectionDescription = styled.p`
  color: ${({ theme }) => theme.colors.text};
  opacity: 0.7;
  margin: 0.75rem 0 1.5rem 0;
  line-height: 1.5;
`;

const ConnectButtonRow = styled.div`
  display: flex;
  flex-wrap: wrap;
  gap: 1rem;
  margin-bottom: 1.5rem;
`;

const ConnectButton = styled.button`
  background: ${({ theme }) => theme.main};
  border: none;
  border-radius: 0.5rem;
  color: #fff;
  padding: 0.7rem 1.25rem;
  font-weight: 600;
  cursor: pointer;
  transition: transform 0.2s ease, box-shadow 0.2s ease;

  &:hover {
    transform: translateY(-2px);
    box-shadow: 0 4px 12px ${({ theme }) => theme.main}66;
  }
`;

const ConnectionList = styled.div`
  display: flex;
  flex-direction: column;
  gap: 1rem;
`;

const ConnectionCard = styled.div`
  border: 1px solid ${({ theme }) => theme.colors.cardBorder};
  border-radius: 0.75rem;
  padding: 1.25rem;
`;

const ConnectionHeader = styled.div`
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  gap: 1rem;
  flex-wrap: wrap;
`;

const ConnectionTitle = styled.strong`
  color: ${({ theme }) => theme.colors.text};
  font-size: 1.05rem;
`;

const ConnectionMeta = styled.p`
  margin: 0.35rem 0 0 0;
  font-size: 0.85rem;
  color: ${({ theme }) => theme.colors.text};
  opacity: 0.65;
`;

const ConnectionActions = styled.div`
  display: flex;
  gap: 0.5rem;
  flex-wrap: wrap;
`;

const SmallButton = styled.button`
  background: transparent;
  border: 1px solid ${({ theme }) => theme.colors.cardBorder};
  border-radius: 0.5rem;
  color: ${({ theme }) => theme.colors.text};
  padding: 0.45rem 0.9rem;
  font-weight: 600;
  font-size: 0.85rem;
  cursor: pointer;

  &:hover {
    background: ${({ theme }) => theme.darkMode ? 'rgba(255, 255, 255, 0.1)' : 'rgba(0, 0, 0, 0.1)'};
  }

  &:disabled {
    opacity: 0.5;
    cursor: not-allowed;
  }
`;

const DangerButton = styled(SmallButton)`
  color: #ff6b6b;
  border-color: rgba(255, 107, 107, 0.4);

  &:hover {
    background: rgba(255, 71, 87, 0.1);
  }
`;

const ResourceForm = styled.div`
  margin-top: 1rem;
  display: flex;
  gap: 0.5rem;
  flex-wrap: wrap;
`;

const ResourceInput = styled.input`
  flex: 1;
  min-width: 200px;
  background: ${({ theme }) => theme.darkMode ? 'rgba(255, 255, 255, 0.05)' : 'rgba(0, 0, 0, 0.05)'};
  border: 1px solid ${({ theme }) => theme.colors.cardBorder};
  border-radius: 0.5rem;
  padding: 0.6rem 0.8rem;
  color: ${({ theme }) => theme.colors.text};

  &::placeholder {
    color: ${({ theme }) => theme.darkMode ? 'rgba(255, 255, 255, 0.4)' : 'rgba(0, 0, 0, 0.4)'};
  }
`;

const ResourceTagList = styled.div`
  margin-top: 0.75rem;
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem;
`;

const ResourceTag = styled.span`
  background: ${({ theme }) => theme.darkMode ? 'rgba(255, 255, 255, 0.1)' : 'rgba(0, 0, 0, 0.08)'};
  color: ${({ theme }) => theme.colors.text};
  border-radius: 999px;
  padding: 0.25rem 0.75rem;
  font-size: 0.8rem;
`;

const EmptyState = styled.p`
  color: ${({ theme }) => theme.colors.text};
  opacity: 0.6;
`;

const AlertBanner = styled.div<{ $tone: 'error' | 'success' }>`
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 1rem;
  margin: 0 0 1.25rem 0;
  padding: 0.85rem 1rem;
  border-radius: 0.5rem;
  border: 1px solid
    ${({ $tone }) => ($tone === 'error' ? 'rgba(255, 107, 107, 0.45)' : 'rgba(46, 204, 113, 0.45)')};
  background: ${({ $tone }) =>
    $tone === 'error' ? 'rgba(255, 71, 87, 0.12)' : 'rgba(46, 204, 113, 0.12)'};
  color: ${({ theme }) => theme.colors.text};
  font-size: 0.9rem;
  line-height: 1.4;
`;

const AlertDismiss = styled.button`
  background: transparent;
  border: none;
  color: inherit;
  font-size: 1.25rem;
  line-height: 1;
  cursor: pointer;
  opacity: 0.7;
  padding: 0;

  &:hover {
    opacity: 1;
  }
`;

const SyncErrorText = styled.p`
  margin: 0.75rem 0 0 0;
  font-size: 0.85rem;
  color: #ff6b6b;
  line-height: 1.4;
`;

const ProgressWrap = styled.div`
  margin-top: 0.85rem;
`;

const ProgressTrack = styled.div`
  width: 100%;
  height: 8px;
  border-radius: 999px;
  overflow: hidden;
  background: ${({ theme }) =>
    theme.darkMode ? 'rgba(255, 255, 255, 0.12)' : 'rgba(0, 0, 0, 0.12)'};
`;

const ProgressFill = styled.div<{ $percent: number | null }>`
  height: 100%;
  width: ${({ $percent }) => ($percent == null ? '40%' : `${$percent}%`)};
  border-radius: 999px;
  background: ${({ theme }) => theme.main};
  transition: width 0.25s ease;
  ${({ $percent }) =>
    $percent == null
      ? `
    animation: sync-indeterminate 1.2s ease-in-out infinite;
    @keyframes sync-indeterminate {
      0% { transform: translateX(-100%); }
      100% { transform: translateX(250%); }
    }
  `
      : ''}
`;

const ProgressLabel = styled.p`
  margin: 0.4rem 0 0 0;
  font-size: 0.8rem;
  color: ${({ theme }) => theme.colors.text};
  opacity: 0.7;
`;

const PROVIDER_LABELS: Record<DriveProvider, string> = {
  google: "Google Drive",
  microsoft: "OneDrive",
};

type PendingAction = 'sync' | 'save' | 'disconnect';

type DriveConnectionsSectionProps = {
  kind: DriveConnectionKind;
  title: string;
  description?: string;
  connectIntent: DriveConnectIntent;
  onSynced?: () => void;
};

const DriveConnectionsSection = ({
  kind,
  title,
  description,
  connectIntent,
  onSynced,
}: DriveConnectionsSectionProps): JSX.Element => {
  const [connections, setConnections] = useState<DriveConnectionType[]>([]);
  const [loading, setLoading] = useState(true);
  const [loadError, setLoadError] = useState(false);
  const [connectError, setConnectError] = useState<string | null>(null);
  const [syncBanner, setSyncBanner] = useState<{ tone: 'error' | 'success'; message: string } | null>(
    null
  );
  const [resourceInputs, setResourceInputs] = useState<Record<number, string>>({});
  const [pendingAction, setPendingAction] = useState<Record<number, PendingAction | undefined>>({});

  const loadConnections = useCallback(async () => {
    setLoading(true);
    setLoadError(false);
    try {
      const all = await fetchDriveConnections();
      setConnections(all.filter((conn) => (conn.kind || 'personal') === kind));
    } catch {
      setLoadError(true);
    } finally {
      setLoading(false);
    }
  }, [kind]);

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

  const setAction = (id: number, action?: PendingAction) => {
    setPendingAction((prev) => ({ ...prev, [id]: action }));
  };

  const upsertConnection = (updated: DriveConnectionType) => {
    setConnections((prev) => {
      const exists = prev.some((conn) => conn.id === updated.id);
      if (!exists) {
        return (updated.kind || 'personal') === kind ? [...prev, updated] : prev;
      }
      return prev.map((conn) => (conn.id === updated.id ? { ...conn, ...updated } : conn));
    });
  };

  const handleDisconnect = async (id: number) => {
    setAction(id, 'disconnect');
    try {
      await disconnectDriveConnection(id);
      setConnections((prev) => prev.filter((conn) => conn.id !== id));
    } catch (err) {
      console.log(err);
      setSyncBanner({ tone: 'error', message: 'Could not disconnect this drive. Try again.' });
    } finally {
      setAction(id, undefined);
    }
  };

  const handleSync = async (id: number) => {
    setAction(id, 'sync');
    setSyncBanner(null);
    try {
      const enqueued = await syncDriveConnection(id);
      upsertConnection(enqueued.connection);

      const settled =
        enqueued.connection.last_sync_status === 'pending'
          ? await waitForDriveSyncSettlement(id, {
              onProgress: (connection) => upsertConnection(connection),
            })
          : enqueued.connection;

      upsertConnection(settled);

      if (settled.last_sync_status === 'error') {
        setSyncBanner({
          tone: 'error',
          message: formatDriveSyncError(settled.last_sync_error),
        });
      } else if (settled.last_sync_status === 'ok') {
        setSyncBanner({ tone: 'success', message: 'Drive sync finished.' });
        onSynced?.();
      }
    } catch (err) {
      console.error(err);
      const message =
        err instanceof Error ? err.message : 'Drive sync failed. Try again.';
      setSyncBanner({ tone: 'error', message });
      await loadConnections();
    } finally {
      setAction(id, undefined);
    }
  };

  const handleSaveResources = async (id: number) => {
    const resourceIds = parseResourceIdsInput(resourceInputs[id] || '');
    if (resourceIds.length === 0) {
      return;
    }
    setAction(id, 'save');
    try {
      const updated = await saveDriveResourceSelection(id, {
        resource_ids: resourceIds,
        resource_labels: resourceIds,
      });
      setConnections((prev) => prev.map((conn) => (conn.id === id ? { ...conn, ...updated } : conn)));
      setResourceInputs((prev) => ({ ...prev, [id]: '' }));
    } catch (err) {
      console.log(err);
      setSyncBanner({ tone: 'error', message: 'Could not save folder selection. Try again.' });
    } finally {
      setAction(id, undefined);
    }
  };

  return (
    <Section>
      <SectionTitle>{title}</SectionTitle>
      {description && <SectionDescription>{description}</SectionDescription>}

      {syncBanner && (
        <AlertBanner $tone={syncBanner.tone} role="alert">
          <span>{syncBanner.message}</span>
          <AlertDismiss
            type="button"
            aria-label="Dismiss"
            onClick={() => setSyncBanner(null)}
          >
            ×
          </AlertDismiss>
        </AlertBanner>
      )}

      <ConnectButtonRow>
        <ConnectButton
          type="button"
          onClick={() => {
            setConnectError(null);
            void connectDrive('google', connectIntent).catch((err) => {
              console.error(err);
              setConnectError('Could not start Google Drive connect. Try again.');
            });
          }}
        >
          Connect Google Drive
        </ConnectButton>
        <ConnectButton
          type="button"
          onClick={() => {
            setConnectError(null);
            void connectDrive('microsoft', connectIntent).catch((err) => {
              console.error(err);
              setConnectError('Could not start OneDrive connect. Try again.');
            });
          }}
        >
          Connect OneDrive
        </ConnectButton>
      </ConnectButtonRow>

      {connectError && <EmptyState>{connectError}</EmptyState>}

      {loading ? (
        <EmptyState>Loading connections…</EmptyState>
      ) : loadError ? (
        <EmptyState>Could not load drive connections. Try again later.</EmptyState>
      ) : connections.length === 0 ? (
        <EmptyState>No drives connected yet.</EmptyState>
      ) : (
        <ConnectionList>
          {connections.map((conn) => {
            const action = pendingAction[conn.id];
            const selectedLabels = conn.selected_resource_labels?.length
              ? conn.selected_resource_labels
              : conn.selected_resource_ids || [];
            const isSyncing = action === 'sync' || conn.last_sync_status === 'pending';
            const progressPercent = isSyncing ? driveSyncProgressPercent(conn) : null;
            const processed = conn.sync_processed ?? 0;
            const total = conn.sync_total ?? 0;

            return (
              <ConnectionCard key={conn.id}>
                <ConnectionHeader>
                  <div>
                    <ConnectionTitle>{PROVIDER_LABELS[conn.provider] || conn.provider}</ConnectionTitle>
                    <ConnectionMeta>
                      {conn.external_account_email || 'Connected account'}
                      {conn.last_sync_status ? ` · ${conn.last_sync_status}` : ''}
                      {conn.last_sync_at
                        ? ` · Last synced ${new Date(conn.last_sync_at).toLocaleString()}`
                        : ''}
                    </ConnectionMeta>
                  </div>
                  <ConnectionActions>
                    <SmallButton
                      type="button"
                      onClick={() => handleSync(conn.id)}
                      disabled={Boolean(action) || conn.last_sync_status === 'pending'}
                    >
                      {isSyncing ? 'Syncing…' : 'Sync now'}
                    </SmallButton>
                    <DangerButton
                      type="button"
                      onClick={() => handleDisconnect(conn.id)}
                      disabled={Boolean(action)}
                    >
                      {action === 'disconnect' ? 'Disconnecting…' : 'Disconnect'}
                    </DangerButton>
                  </ConnectionActions>
                </ConnectionHeader>

                {isSyncing && (
                  <ProgressWrap aria-label="Drive sync progress">
                    <ProgressTrack>
                      <ProgressFill $percent={progressPercent} />
                    </ProgressTrack>
                    <ProgressLabel>
                      {progressPercent == null
                        ? 'Discovering files…'
                        : `${processed} / ${total} files (${progressPercent}%)`}
                    </ProgressLabel>
                  </ProgressWrap>
                )}

                {conn.last_sync_status === 'error' && conn.last_sync_error && (
                  <SyncErrorText>{formatDriveSyncError(conn.last_sync_error)}</SyncErrorText>
                )}

                {selectedLabels.length > 0 && (
                  <ResourceTagList>
                    {selectedLabels.map((label, idx) => (
                      <ResourceTag key={`${conn.id}-${idx}`}>{label}</ResourceTag>
                    ))}
                  </ResourceTagList>
                )}

                <ResourceForm>
                  <ResourceInput
                    type="text"
                    placeholder="Folder or file IDs, comma separated"
                    value={resourceInputs[conn.id] || ''}
                    onChange={(e) =>
                      setResourceInputs((prev) => ({ ...prev, [conn.id]: e.target.value }))
                    }
                  />
                  <SmallButton
                    type="button"
                    onClick={() => handleSaveResources(conn.id)}
                    disabled={action === 'save' || !(resourceInputs[conn.id] || '').trim()}
                  >
                    {action === 'save' ? 'Saving…' : 'Save folders'}
                  </SmallButton>
                </ResourceForm>
              </ConnectionCard>
            );
          })}
        </ConnectionList>
      )}
    </Section>
  );
};

export default DriveConnectionsSection;
