import { useState, useEffect, useRef, useCallback } from 'react';
import { useParams, useSearchParams, useNavigate } from 'react-router-dom';
import { TagDetail, Package, PaginatedResponse } from '../types';
import { listTags, uploadArtifact, getDownloadUrl, getPackage } from '../api';
import { Breadcrumb } from '../components/Breadcrumb';
import { Badge } from '../components/Badge';
import { SearchInput } from '../components/SearchInput';
import { SortDropdown, SortOption } from '../components/SortDropdown';
import { FilterChip, FilterChipGroup } from '../components/FilterChip';
import { DataTable } from '../components/DataTable';
import { Pagination } from '../components/Pagination';
import './Home.css';
import './PackagePage.css';

const SORT_OPTIONS: SortOption[] = [
  { value: 'name', label: 'Name' },
  { value: 'created_at', label: 'Created' },
];

function formatBytes(bytes: number): string {
  if (bytes === 0) return '0 B';
  const k = 1024;
  const sizes = ['B', 'KB', 'MB', 'GB', 'TB'];
  const i = Math.floor(Math.log(bytes) / Math.log(k));
  return parseFloat((bytes / Math.pow(k, i)).toFixed(1)) + ' ' + sizes[i];
}

function CopyButton({ text }: { text: string }) {
  const [copied, setCopied] = useState(false);

  const handleCopy = async (e: React.MouseEvent) => {
    e.preventDefault();
    e.stopPropagation();
    await navigator.clipboard.writeText(text);
    setCopied(true);
    setTimeout(() => setCopied(false), 2000);
  };

  return (
    <button className="copy-btn" onClick={handleCopy} title="Copy to clipboard">
      {copied ? (
        <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2">
          <polyline points="20 6 9 17 4 12" />
        </svg>
      ) : (
        <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2">
          <rect x="9" y="9" width="13" height="13" rx="2" ry="2" />
          <path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1" />
        </svg>
      )}
    </button>
  );
}

function PackagePage() {
  const { projectName, packageName } = useParams<{ projectName: string; packageName: string }>();
  const navigate = useNavigate();
  const [searchParams, setSearchParams] = useSearchParams();

  const [pkg, setPkg] = useState<Package | null>(null);
  const [tagsData, setTagsData] = useState<PaginatedResponse<TagDetail> | null>(null);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState<string | null>(null);
  const [uploading, setUploading] = useState(false);
  const [uploadResult, setUploadResult] = useState<string | null>(null);
  const [tag, setTag] = useState('');
  const fileInputRef = useRef<HTMLInputElement>(null);

  // Get params from URL
  const page = parseInt(searchParams.get('page') || '1', 10);
  const search = searchParams.get('search') || '';
  const sort = searchParams.get('sort') || 'name';
  const order = (searchParams.get('order') || 'asc') as 'asc' | 'desc';

  const updateParams = useCallback(
    (updates: Record<string, string | undefined>) => {
      const newParams = new URLSearchParams(searchParams);
      Object.entries(updates).forEach(([key, value]) => {
        if (value === undefined || value === '' || (key === 'page' && value === '1')) {
          newParams.delete(key);
        } else {
          newParams.set(key, value);
        }
      });
      setSearchParams(newParams);
    },
    [searchParams, setSearchParams]
  );

  const loadData = useCallback(async () => {
    if (!projectName || !packageName) return;

    try {
      setLoading(true);
      const [pkgData, tagsResult] = await Promise.all([
        getPackage(projectName, packageName),
        listTags(projectName, packageName, { page, search, sort, order }),
      ]);
      setPkg(pkgData);
      setTagsData(tagsResult);
      setError(null);
    } catch (err) {
      setError(err instanceof Error ? err.message : 'Failed to load data');
    } finally {
      setLoading(false);
    }
  }, [projectName, packageName, page, search, sort, order]);

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

  // Keyboard navigation - go back with backspace
  useEffect(() => {
    const handleKeyDown = (e: KeyboardEvent) => {
      if (e.key === 'Backspace' && !['INPUT', 'TEXTAREA'].includes((e.target as HTMLElement).tagName)) {
        e.preventDefault();
        navigate(`/project/${projectName}`);
      }
    };
    window.addEventListener('keydown', handleKeyDown);
    return () => window.removeEventListener('keydown', handleKeyDown);
  }, [navigate, projectName]);

  async function handleUpload(e: React.FormEvent) {
    e.preventDefault();
    const file = fileInputRef.current?.files?.[0];
    if (!file) {
      setError('Please select a file');
      return;
    }

    try {
      setUploading(true);
      setError(null);
      const result = await uploadArtifact(projectName!, packageName!, file, tag || undefined);
      setUploadResult(`Uploaded successfully! Artifact ID: ${result.artifact_id}`);
      setTag('');
      if (fileInputRef.current) {
        fileInputRef.current.value = '';
      }
      loadData();
    } catch (err) {
      setError(err instanceof Error ? err.message : 'Upload failed');
    } finally {
      setUploading(false);
    }
  }

  const handleSearchChange = (value: string) => {
    updateParams({ search: value, page: '1' });
  };

  const handleSortChange = (newSort: string, newOrder: 'asc' | 'desc') => {
    updateParams({ sort: newSort, order: newOrder, page: '1' });
  };

  const handlePageChange = (newPage: number) => {
    updateParams({ page: String(newPage) });
  };

  const clearFilters = () => {
    setSearchParams({});
  };

  const hasActiveFilters = search !== '';
  const tags = tagsData?.items || [];
  const pagination = tagsData?.pagination;

  const columns = [
    {
      key: 'name',
      header: 'Tag',
      sortable: true,
      render: (t: TagDetail) => <strong>{t.name}</strong>,
    },
    {
      key: 'artifact_id',
      header: 'Artifact ID',
      render: (t: TagDetail) => (
        <div className="artifact-id-cell">
          <code className="artifact-id">{t.artifact_id.substring(0, 12)}...</code>
          <CopyButton text={t.artifact_id} />
        </div>
      ),
    },
    {
      key: 'size',
      header: 'Size',
      render: (t: TagDetail) => <span>{formatBytes(t.artifact_size)}</span>,
    },
    {
      key: 'content_type',
      header: 'Type',
      render: (t: TagDetail) => (
        <span className="content-type">{t.artifact_content_type || '-'}</span>
      ),
    },
    {
      key: 'original_name',
      header: 'Filename',
      className: 'cell-truncate',
      render: (t: TagDetail) => (
        <span title={t.artifact_original_name || undefined}>{t.artifact_original_name || '-'}</span>
      ),
    },
    {
      key: 'created_at',
      header: 'Created',
      sortable: true,
      render: (t: TagDetail) => (
        <div className="created-cell">
          <span>{new Date(t.created_at).toLocaleString()}</span>
          <span className="created-by">by {t.created_by}</span>
        </div>
      ),
    },
    {
      key: 'actions',
      header: 'Actions',
      render: (t: TagDetail) => (
        <a
          href={getDownloadUrl(projectName!, packageName!, t.name)}
          className="btn btn-secondary btn-small"
          download
        >
          Download
        </a>
      ),
    },
  ];

  if (loading && !tagsData) {
    return <div className="loading">Loading...</div>;
  }

  return (
    <div className="home">
      <Breadcrumb
        items={[
          { label: 'Projects', href: '/' },
          { label: projectName!, href: `/project/${projectName}` },
          { label: packageName! },
        ]}
      />

      <div className="page-header">
        <div className="page-header__info">
          <div className="page-header__title-row">
            <h1>{packageName}</h1>
            {pkg && <Badge variant="default">{pkg.format}</Badge>}
          </div>
          {pkg?.description && <p className="description">{pkg.description}</p>}
          <div className="page-header__meta">
            <span className="meta-item">
              in <a href={`/project/${projectName}`}>{projectName}</a>
            </span>
            {pkg && (
              <>
                <span className="meta-item">Created {new Date(pkg.created_at).toLocaleDateString()}</span>
                {pkg.updated_at !== pkg.created_at && (
                  <span className="meta-item">Updated {new Date(pkg.updated_at).toLocaleDateString()}</span>
                )}
              </>
            )}
          </div>
          {pkg && (pkg.tag_count !== undefined || pkg.artifact_count !== undefined) && (
            <div className="package-header-stats">
              {pkg.tag_count !== undefined && (
                <span className="stat-item">
                  <strong>{pkg.tag_count}</strong> tags
                </span>
              )}
              {pkg.artifact_count !== undefined && (
                <span className="stat-item">
                  <strong>{pkg.artifact_count}</strong> artifacts
                </span>
              )}
              {pkg.total_size !== undefined && pkg.total_size > 0 && (
                <span className="stat-item">
                  <strong>{formatBytes(pkg.total_size)}</strong> total
                </span>
              )}
              {pkg.latest_tag && (
                <span className="stat-item">
                  Latest: <strong className="accent">{pkg.latest_tag}</strong>
                </span>
              )}
            </div>
          )}
        </div>
      </div>

      {error && <div className="error-message">{error}</div>}
      {uploadResult && <div className="success-message">{uploadResult}</div>}

      <div className="upload-section card">
        <h3>Upload Artifact</h3>
        <form onSubmit={handleUpload} className="upload-form">
          <div className="form-group">
            <label htmlFor="file">File</label>
            <input id="file" type="file" ref={fileInputRef} required />
          </div>
          <div className="form-group">
            <label htmlFor="tag">Tag (optional)</label>
            <input
              id="tag"
              type="text"
              value={tag}
              onChange={(e) => setTag(e.target.value)}
              placeholder="v1.0.0, latest, stable..."
            />
          </div>
          <button type="submit" className="btn btn-primary" disabled={uploading}>
            {uploading ? 'Uploading...' : 'Upload'}
          </button>
        </form>
      </div>

      <div className="section-header">
        <h2>Tags / Versions</h2>
      </div>

      <div className="list-controls">
        <SearchInput
          value={search}
          onChange={handleSearchChange}
          placeholder="Filter tags..."
          className="list-controls__search"
        />
        <SortDropdown options={SORT_OPTIONS} value={sort} order={order} onChange={handleSortChange} />
      </div>

      {hasActiveFilters && (
        <FilterChipGroup onClearAll={clearFilters}>
          {search && <FilterChip label="Filter" value={search} onRemove={() => handleSearchChange('')} />}
        </FilterChipGroup>
      )}

      <DataTable
        data={tags}
        columns={columns}
        keyExtractor={(t) => t.id}
        emptyMessage={
          hasActiveFilters
            ? 'No tags match your filters. Try adjusting your search.'
            : 'No tags yet. Upload an artifact with a tag to create one!'
        }
        onSort={(key) => {
          if (key === sort) {
            handleSortChange(key, order === 'asc' ? 'desc' : 'asc');
          } else {
            handleSortChange(key, 'asc');
          }
        }}
        sortKey={sort}
        sortOrder={order}
      />

      {pagination && pagination.total_pages > 1 && (
        <Pagination
          page={pagination.page}
          totalPages={pagination.total_pages}
          total={pagination.total}
          limit={pagination.limit}
          onPageChange={handlePageChange}
        />
      )}

      <div className="usage-section card">
        <h3>Usage</h3>
        <p>Download artifacts using:</p>
        <pre>
          <code>curl -O {window.location.origin}/api/v1/project/{projectName}/{packageName}/+/latest</code>
        </pre>
        <p>Or with a specific tag:</p>
        <pre>
          <code>curl -O {window.location.origin}/api/v1/project/{projectName}/{packageName}/+/v1.0.0</code>
        </pre>
      </div>
    </div>
  );
}

export default PackagePage;
