import { useCallback, useContext, useEffect, useState } from "react";
import { Link, useSearchParams } from "react-router-dom";
import { Document, DocumentType } from "../../data";
import { AxiosResponse } from "axios";
import { axiosInstance } from "../../../axiosApi";
import Header2 from "../../components/Header2/Header2";
import ParticleBackground from "../../components/ParticleBackground/ParticleBackground";
import DriveConnectionsSection from "../../components/DriveConnectionsSection/DriveConnectionsSection";
import { AccountContext } from "../../contexts/AccountContext";
import { useSubscription } from "../../hooks/useSubscription";
import styled from "styled-components";

// Styled Components
const PageContainer = styled.div`
  position: relative;
  width: 100vw;
  height: 100vh;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  color: ${({ theme }) => theme.colors.text};
  font-family: 'Inter', sans-serif;
`;

const ContentWrapper = styled.div`
  flex: 1;
  overflow-y: auto;
  padding: 6rem 2rem 2rem 2rem;
  display: flex;
  flex-direction: column;
  align-items: center;
  z-index: 5;

  &::-webkit-scrollbar {
    width: 8px;
  }
  &::-webkit-scrollbar-track {
    background: transparent;
  }
  &::-webkit-scrollbar-thumb {
    background: rgba(255, 255, 255, 0.2);
    border-radius: 4px;
  }
`;

const GlassCard = 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 CardTitle = styled.h2`
  font-size: 1.8rem;
  margin-bottom: 1.5rem;
  color: ${({ theme }) => theme.colors.text};
  border-bottom: 1px solid ${({ theme }) => theme.colors.cardBorder};
  padding-bottom: 1rem;
`;

const TabRow = styled.div`
  display: flex;
  gap: 0.5rem;
  margin-bottom: 1.25rem;
  flex-wrap: wrap;
`;

const TabButton = styled.button<{ $active: boolean }>`
  background: ${({ $active, theme }) => ($active ? theme.main : 'transparent')};
  border: 1px solid ${({ theme }) => theme.colors.cardBorder};
  border-radius: 0.5rem;
  color: ${({ $active, theme }) => ($active ? '#fff' : theme.colors.text)};
  padding: 0.55rem 1rem;
  font-weight: 600;
  cursor: pointer;
`;

const Toolbar = styled.div`
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem;
  align-items: center;
  margin-bottom: 1rem;
`;

const SearchInput = styled.input`
  flex: 1;
  min-width: 180px;
  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 PaginationRow = styled.div`
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 1rem;
  flex-wrap: wrap;
  margin-top: 1rem;
  color: ${({ theme }) => theme.colors.text};
  opacity: 0.8;
  font-size: 0.9rem;
`;

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

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

const StyledTable = styled.table`
  width: 100%;
  border-collapse: collapse;
  margin-top: 1rem;
`;

const Th = styled.th`
  text-align: left;
  padding: 1rem;
  border-bottom: 1px solid ${({ theme }) => theme.colors.cardBorder};
  color: ${({ theme }) => theme.colors.text};
  opacity: 0.7;
  font-weight: 600;
`;

const SortableTh = styled(Th)`
  cursor: pointer;
  user-select: none;

  &:hover {
    opacity: 1;
  }
`;

const Td = styled.td`
  padding: 1rem;
  border-bottom: 1px solid ${({ theme }) => theme.colors.cardBorder};
  color: ${({ theme }) => theme.colors.text};
`;

const StyledButton = styled.button`
  background: ${({ theme }) => theme.main};
  border: none;
  border-radius: 0.5rem;
  color: #fff;
  padding: 0.8rem 1.5rem;
  font-weight: 600;
  cursor: pointer;
  transition: transform 0.2s ease, box-shadow 0.2s ease;
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;

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

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

const StyledButtonLink = styled(Link)`
  background: ${({ theme }) => theme.main};
  border: none;
  border-radius: 0.5rem;
  color: #fff;
  padding: 0.8rem 1.5rem;
  font-weight: 600;
  cursor: pointer;
  transition: transform 0.2s ease, box-shadow 0.2s ease;
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  text-decoration: none;

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

const FileInputLabel = styled.label`
  background: ${({ theme }) => theme.main};
  border: none;
  border-radius: 0.5rem;
  color: #fff;
  padding: 0.8rem 1.5rem;
  font-weight: 600;
  cursor: pointer;
  transition: transform 0.2s ease, box-shadow 0.2s ease;
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  margin-right: 1rem;

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

const StatusIcon = styled.span<{ status: 'success' | 'pending' }>`
  color: ${props => props.status === 'success' ? '#4caf50' : '#bdbdbd'};
  font-size: 1.5rem;
`;

const ToggleSwitch = styled.label`
  position: relative;
  display: inline-block;
  width: 50px;
  height: 24px;
`;

const Slider = styled.span`
  position: absolute;
  cursor: pointer;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background-color: ${({ theme }) => theme.darkMode ? 'rgba(255, 255, 255, 0.2)' : 'rgba(0, 0, 0, 0.2)'};
  transition: .4s;
  border-radius: 24px;

  &:before {
    position: absolute;
    content: "";
    height: 16px;
    width: 16px;
    left: 4px;
    bottom: 4px;
    background-color: white;
    transition: .4s;
    border-radius: 50%;
  }
`;

const Checkbox = styled.input`
  opacity: 0;
  width: 0;
  height: 0;

  &:checked + ${Slider} {
    background-color: ${({ theme }) => theme.main};
  }

  &:checked + ${Slider}:before {
    transform: translateX(26px);
  }
  
  &:disabled + ${Slider} {
    opacity: 0.5;
    cursor: not-allowed;
  }
`;

const HelperNote = styled.p`
  margin: 1rem 0 0 0;
  padding-top: 1rem;
  border-top: 1px solid ${({ theme }) => theme.colors.cardBorder};
  color: ${({ theme }) => theme.colors.text};
  opacity: 0.65;
  font-size: 0.9rem;
  line-height: 1.5;
`;

const UpgradeText = styled.p`
  color: ${({ theme }) => theme.colors.text};
  opacity: 0.8;
  line-height: 1.6;
  margin-bottom: 1.5rem;
`;

const SuccessBanner = styled.div`
  width: 100%;
  max-width: 1000px;
  margin-bottom: 1.5rem;
  padding: 1rem 1.5rem;
  border-radius: 0.75rem;
  background: rgba(76, 175, 80, 0.15);
  border: 1px solid rgba(76, 175, 80, 0.4);
  color: ${({ theme }) => theme.colors.text};
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 1rem;
`;

const DismissButton = styled.button`
  background: transparent;
  border: none;
  color: ${({ theme }) => theme.colors.text};
  font-size: 1.1rem;
  cursor: pointer;
  line-height: 1;
  opacity: 0.7;

  &:hover {
    opacity: 1;
  }
`;

const EmptyRow = styled.td`
  padding: 1.5rem 1rem;
  color: ${({ theme }) => theme.colors.text};
  opacity: 0.65;
  text-align: center;
`;

export type DocumentWorkspaceScope = 'personal' | 'company';

type DocumentsListResponse = {
  count: number;
  page: number;
  page_size: number;
  scope: DocumentWorkspaceScope;
  results: DocumentType[];
};

type SortField = 'name' | 'created' | 'processed' | 'active';

type DocumentTableCardProps = {
  scope: DocumentWorkspaceScope;
  showTabs: boolean;
  onScopeChange: (scope: DocumentWorkspaceScope) => void;
  documents: Document[];
  total: number;
  page: number;
  pageSize: number;
  search: string;
  ordering: string;
  loading: boolean;
  onSearchChange: (value: string) => void;
  onSort: (field: SortField) => void;
  onPageChange: (page: number) => void;
  onToggleActive: (id: number, active: boolean) => void;
};

const sortLabel = (field: SortField, ordering: string): string => {
  const labels: Record<SortField, string> = {
    name: 'Name',
    created: 'Date Uploaded',
    processed: 'Processed',
    active: 'Active',
  };
  if (ordering === field) return `${labels[field]} ↑`;
  if (ordering === `-${field}`) return `${labels[field]} ↓`;
  return labels[field];
};

const DocumentStorageTableCard = ({
  scope,
  showTabs,
  onScopeChange,
  documents,
  total,
  page,
  pageSize,
  search,
  ordering,
  loading,
  onSearchChange,
  onSort,
  onPageChange,
  onToggleActive,
}: DocumentTableCardProps): JSX.Element => {
  const title = scope === 'company' ? 'Company documents' : 'Personal documents';
  const totalPages = Math.max(1, Math.ceil(total / pageSize));

  return (
    <GlassCard>
      <CardTitle>{title}</CardTitle>

      {showTabs && (
        <TabRow role="tablist" aria-label="Document workspace">
          <TabButton
            type="button"
            role="tab"
            aria-selected={scope === 'personal'}
            $active={scope === 'personal'}
            onClick={() => onScopeChange('personal')}
          >
            Personal
          </TabButton>
          <TabButton
            type="button"
            role="tab"
            aria-selected={scope === 'company'}
            $active={scope === 'company'}
            onClick={() => onScopeChange('company')}
          >
            Company
          </TabButton>
        </TabRow>
      )}

      <Toolbar>
        <SearchInput
          type="search"
          placeholder="Search documents…"
          value={search}
          onChange={(event) => onSearchChange(event.target.value)}
          aria-label="Search documents"
        />
      </Toolbar>

      <div style={{ overflowX: 'auto' }}>
        <StyledTable>
          <thead>
            <tr>
              <SortableTh onClick={() => onSort('name')}>{sortLabel('name', ordering)}</SortableTh>
              <SortableTh onClick={() => onSort('created')}>{sortLabel('created', ordering)}</SortableTh>
              <SortableTh onClick={() => onSort('processed')}>{sortLabel('processed', ordering)}</SortableTh>
              <SortableTh onClick={() => onSort('active')}>{sortLabel('active', ordering)}</SortableTh>
            </tr>
          </thead>
          <tbody>
            {loading ? (
              <tr>
                <EmptyRow colSpan={4}>Loading documents…</EmptyRow>
              </tr>
            ) : documents.length === 0 ? (
              <tr>
                <EmptyRow colSpan={4}>No documents found.</EmptyRow>
              </tr>
            ) : (
              documents.map((doc) => (
                <tr key={doc.id}>
                  <Td>{doc.name}</Td>
                  <Td>{doc.date_uploaded}</Td>
                  <Td>
                    {doc.processed ? (
                      <StatusIcon status="success">✓</StatusIcon>
                    ) : (
                      <StatusIcon status="pending">⏳</StatusIcon>
                    )}
                  </Td>
                  <Td>
                    <ToggleSwitch>
                      <Checkbox
                        type="checkbox"
                        checked={doc.active}
                        onChange={(event) => onToggleActive(doc.id, event.target.checked)}
                      />
                      <Slider />
                    </ToggleSwitch>
                  </Td>
                </tr>
              ))
            )}
          </tbody>
        </StyledTable>
      </div>

      <PaginationRow>
        <span>
          {total === 0
            ? '0 documents'
            : `Showing ${(page - 1) * pageSize + 1}–${Math.min(page * pageSize, total)} of ${total}`}
        </span>
        <div style={{ display: 'flex', gap: '0.5rem' }}>
          <PageButton type="button" disabled={page <= 1} onClick={() => onPageChange(page - 1)}>
            Previous
          </PageButton>
          <PageButton
            type="button"
            disabled={page >= totalPages}
            onClick={() => onPageChange(page + 1)}
          >
            Next
          </PageButton>
        </div>
      </PaginationRow>

      {scope === 'company' && (
        <HelperNote>
          These documents are shared with your whole company workspace. Want to search your own
          files privately? Connect a personal cloud drive in the Cloud drives section below.
        </HelperNote>
      )}
    </GlassCard>
  );
};

type DocumentUploadCardProps = {
  scope: DocumentWorkspaceScope;
  onUploaded: () => void | Promise<void>;
};

const DocumentUploadCard = ({ scope, onUploaded }: DocumentUploadCardProps): JSX.Element => {
  const [selectedFile, setSelectedFile] = useState<File | null>(null);
  const [uploading, setUploading] = useState<boolean>(false);

  const handleDocumentUpload = async (): Promise<void> => {
    if (!selectedFile) {
      return;
    }
    setUploading(true);
    try {
      await axiosInstance.post(
        '/documents/',
        { file: selectedFile },
        {
          headers: { 'Content-Type': 'multipart/form-data' },
          params: { workspace: scope },
        }
      );

      setSelectedFile(null);
      await onUploaded();
    } catch (error) {
      console.log(error);
    } finally {
      setUploading(false);
    }
  };

  const handleFileChange = (event: React.ChangeEvent<HTMLInputElement>) => {
    if (event.target.files && event.target.files.length > 0) {
      setSelectedFile(event.target.files[0]);
    }
  };
  return (
    <GlassCard>
      <CardTitle>Upload a Document</CardTitle>
      <div style={{ display: 'flex', alignItems: 'center', flexWrap: 'wrap', gap: '1rem' }}>
        <FileInputLabel>
          Select File
          <input type="file" hidden onChange={handleFileChange} disabled={uploading} />
        </FileInputLabel>

        {selectedFile && (
          <>
            <span style={{ color: '#fff' }}>{selectedFile.name}</span>
            <StyledButton onClick={handleDocumentUpload} disabled={uploading}>
              {uploading ? 'Uploading…' : 'Upload'}
            </StyledButton>
          </>
        )}
      </div>
    </GlassCard>
  );
};

const PAGE_SIZE = 20;

const DocumentStoragePageInner = (): JSX.Element => {
  const [documents, setDocuments] = useState<Document[]>([]);
  const [total, setTotal] = useState(0);
  const [page, setPage] = useState(1);
  const [searchInput, setSearchInput] = useState('');
  const [search, setSearch] = useState('');
  const [ordering, setOrdering] = useState('-created');
  const [loading, setLoading] = useState(true);
  const { account } = useContext(AccountContext);
  const [searchParams, setSearchParams] = useSearchParams();
  const [showDriveConnectedBanner, setShowDriveConnectedBanner] = useState(false);

  const hasCompany = Boolean(account?.company);
  const [scope, setScope] = useState<DocumentWorkspaceScope>(
    hasCompany ? 'company' : 'personal'
  );

  useEffect(() => {
    if (!hasCompany && scope === 'company') {
      setScope('personal');
    }
  }, [hasCompany, scope]);

  useEffect(() => {
    const handle = window.setTimeout(() => {
      setSearch(searchInput.trim());
      setPage(1);
    }, 300);
    return () => window.clearTimeout(handle);
  }, [searchInput]);

  const fetchDocuments = useCallback(async () => {
    setLoading(true);
    try {
      const { data }: AxiosResponse<DocumentsListResponse> = await axiosInstance.get(
        `/documents/`,
        {
          params: {
            workspace: scope,
            page,
            page_size: PAGE_SIZE,
            search: search || undefined,
            ordering,
          },
        }
      );
      const results = Array.isArray(data?.results) ? data.results : [];
      setTotal(typeof data?.count === 'number' ? data.count : results.length);
      setDocuments(
        results.map(
          (item) =>
            new Document({
              id: item.id,
              name: item.file.replace(/^.*[\\/]/, ''),
              date_uploaded: item.created.substring(0, 10),
              active: item.active,
              processed: item.processed,
            })
        )
      );
    } catch (error) {
      console.log(error);
      setDocuments([]);
      setTotal(0);
    } finally {
      setLoading(false);
    }
  }, [scope, page, search, ordering]);

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

  useEffect(() => {
    if (searchParams.get('drive_connected') === '1') {
      setShowDriveConnectedBanner(true);
      const next = new URLSearchParams(searchParams);
      next.delete('drive_connected');
      setSearchParams(next, { replace: true });
    }
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, []);

  const handleToggleActive = useCallback(async (id: number, active: boolean) => {
    setDocuments((prev) => prev.map((doc) => (doc.id === id ? { ...doc, active } as Document : doc)));
    try {
      await axiosInstance.patch(`documents_details/${id}`, { active });
    } catch (error) {
      console.log(error);
      setDocuments((prev) => prev.map((doc) => (doc.id === id ? { ...doc, active: !active } as Document : doc)));
    }
  }, []);

  const handleSort = (field: SortField) => {
    setPage(1);
    setOrdering((prev) => {
      if (prev === field) return `-${field}`;
      if (prev === `-${field}`) return field;
      return field === 'created' ? '-created' : field;
    });
  };

  const handleScopeChange = (next: DocumentWorkspaceScope) => {
    setScope(next);
    setPage(1);
  };

  return (
    <>
      {showDriveConnectedBanner && (
        <SuccessBanner>
          <span>Drive connected. Choose folders below to include them in your knowledge base.</span>
          <DismissButton
            type="button"
            aria-label="Dismiss"
            onClick={() => setShowDriveConnectedBanner(false)}
          >
            ×
          </DismissButton>
        </SuccessBanner>
      )}

      <DocumentStorageTableCard
        scope={scope}
        showTabs={hasCompany}
        onScopeChange={handleScopeChange}
        documents={documents}
        total={total}
        page={page}
        pageSize={PAGE_SIZE}
        search={searchInput}
        ordering={ordering}
        loading={loading}
        onSearchChange={setSearchInput}
        onSort={handleSort}
        onPageChange={setPage}
        onToggleActive={handleToggleActive}
      />
      <DocumentUploadCard scope={scope} onUploaded={fetchDocuments} />

      <DriveConnectionsSection
        kind="personal"
        title="Cloud drives"
        description="Connect your personal Google Drive or OneDrive so its files can be searched in chat."
        connectIntent="link_drive"
        onSynced={fetchDocuments}
      />

      {account?.is_company_manager && (
        <DriveConnectionsSection
          kind="company"
          title="Company knowledge sources"
          description="Connect a shared Google Shared Drive or Microsoft 365 site so your whole team can search these files in chat."
          connectIntent="link_company_drive"
          onSynced={fetchDocuments}
        />
      )}
    </>
  );
};

const DocumentStoragePage = (): JSX.Element => {
  const { hasRag, loading } = useSubscription();

  return (
    <PageContainer>
      <ParticleBackground />
      <Header2 />
      <ContentWrapper>
        {loading ? (
          <GlassCard>
            <CardTitle>Loading…</CardTitle>
          </GlassCard>
        ) : hasRag ? (
          <DocumentStoragePageInner />
        ) : (
          <GlassCard>
            <CardTitle>Unlock document storage</CardTitle>
            <UpgradeText>
              Document uploads and cloud drive connections are available on plans that include
              RAG document search. Upgrade your plan to start uploading files and connecting
              Google Drive or OneDrive.
            </UpgradeText>
            <StyledButtonLink to="/account/">Upgrade in Billing</StyledButtonLink>
          </GlassCard>
        )}
      </ContentWrapper>
    </PageContainer>
  );
};

export default DocumentStoragePage;
