import { useState, useEffect, useCallback } from 'react';
import { useParams, useSearchParams, useNavigate, useLocation } from 'react-router-dom';
import { Project, Package, PaginatedResponse, AccessLevel } from '../types';
import { getProject, listPackages, createPackage, getMyProjectAccess, UnauthorizedError, ForbiddenError } from '../api';
import { Breadcrumb } from '../components/Breadcrumb';
import { Badge } from '../components/Badge';
import { DataTable } from '../components/DataTable';
import { SearchInput } from '../components/SearchInput';
import { FilterChip, FilterChipGroup } from '../components/FilterChip';
import { Pagination } from '../components/Pagination';
import { useAuth } from '../contexts/AuthContext';
import './Home.css';

const FORMAT_OPTIONS = ['generic', 'npm', 'pypi', 'docker', 'deb', 'rpm', 'maven', 'nuget', 'helm'];

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 ProjectPage() {
  const { projectName } = useParams<{ projectName: string }>();
  const navigate = useNavigate();
  const location = useLocation();
  const [searchParams, setSearchParams] = useSearchParams();
  const { user } = useAuth();

  const [project, setProject] = useState<Project | null>(null);
  const [packagesData, setPackagesData] = useState<PaginatedResponse<Package> | null>(null);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState<string | null>(null);
  const [accessDenied, setAccessDenied] = useState(false);
  const [showForm, setShowForm] = useState(false);
  const [newPackage, setNewPackage] = useState({ name: '', description: '', format: 'generic', platform: 'any' });
  const [creating, setCreating] = useState(false);
  const [accessLevel, setAccessLevel] = useState<AccessLevel | null>(null);
  const [isOwner, setIsOwner] = useState(false);

  // Derived permissions
  const canWrite = accessLevel === 'write' || accessLevel === 'admin';
  const canAdmin = accessLevel === 'admin';

  // 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 format = searchParams.get('format') || '';

  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) return;

    try {
      setLoading(true);
      setAccessDenied(false);
      const [projectData, packagesResult, accessResult] = await Promise.all([
        getProject(projectName),
        listPackages(projectName, { page, search, sort, order, format: format || undefined }),
        getMyProjectAccess(projectName),
      ]);
      setProject(projectData);
      setPackagesData(packagesResult);
      setAccessLevel(accessResult.access_level);
      setIsOwner(accessResult.is_owner);
      setError(null);
    } catch (err) {
      if (err instanceof UnauthorizedError) {
        navigate('/login', { state: { from: location.pathname } });
        return;
      }
      if (err instanceof ForbiddenError) {
        setAccessDenied(true);
        setError('You do not have access to this project');
        setLoading(false);
        return;
      }
      setError(err instanceof Error ? err.message : 'Failed to load data');
    } finally {
      setLoading(false);
    }
  }, [projectName, page, search, sort, order, format, navigate, location.pathname]);

  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('/');
      }
    };
    window.addEventListener('keydown', handleKeyDown);
    return () => window.removeEventListener('keydown', handleKeyDown);
  }, [navigate]);

  async function handleCreatePackage(e: React.FormEvent) {
    e.preventDefault();
    try {
      setCreating(true);
      await createPackage(projectName!, newPackage);
      setNewPackage({ name: '', description: '', format: 'generic', platform: 'any' });
      setShowForm(false);
      loadData();
    } catch (err) {
      setError(err instanceof Error ? err.message : 'Failed to create package');
    } finally {
      setCreating(false);
    }
  }

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

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

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

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

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

  const hasActiveFilters = search !== '' || format !== '';
  const packages = packagesData?.items || [];
  const pagination = packagesData?.pagination;

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

  if (accessDenied) {
    return (
      <div className="home">
        <Breadcrumb items={[{ label: 'Projects', href: '/' }]} />
        <div className="error-message" style={{ textAlign: 'center', padding: '48px 24px' }}>
          <h2>Access Denied</h2>
          <p>You do not have permission to view this project.</p>
          {!user && (
            <p style={{ marginTop: '16px' }}>
              <a href="/login" className="btn btn-primary">Sign in</a>
            </p>
          )}
        </div>
      </div>
    );
  }

  if (!project) {
    return <div className="error-message">Project not found</div>;
  }

  return (
    <div className="home">
      <Breadcrumb
        items={[
          { label: 'Projects', href: '/' },
          { label: project.name },
        ]}
      />

      <div className="page-header">
        <div className="page-header__info">
          <div className="page-header__title-row">
            <h1>{project.name}</h1>
            <Badge variant={project.is_public ? 'public' : 'private'}>
              {project.is_public ? 'Public' : 'Private'}
            </Badge>
            {accessLevel && (
              <Badge variant={accessLevel === 'admin' ? 'success' : accessLevel === 'write' ? 'info' : 'default'}>
                {isOwner ? 'Owner' : accessLevel.charAt(0).toUpperCase() + accessLevel.slice(1)}
              </Badge>
            )}
          </div>
          {project.description && <p className="description">{project.description}</p>}
          <div className="page-header__meta">
            <span className="meta-item">Created {new Date(project.created_at).toLocaleDateString()}</span>
            {project.updated_at !== project.created_at && (
              <span className="meta-item">Updated {new Date(project.updated_at).toLocaleDateString()}</span>
            )}
            <span className="meta-item">by {project.created_by}</span>
          </div>
        </div>
        <div className="page-header__actions">
          {canAdmin && (
            <button
              className="btn btn-secondary"
              onClick={() => navigate(`/project/${projectName}/settings`)}
              title="Project Settings"
            >
              <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
                <circle cx="12" cy="12" r="3" />
                <path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1 0 2.83 2 2 0 0 1-2.83 0l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-2 2 2 2 0 0 1-2-2v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83 0 2 2 0 0 1 0-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1-2-2 2 2 0 0 1 2-2h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 0-2.83 2 2 0 0 1 2.83 0l.06.06a1.65 1.65 0 0 0 1.82.33H9a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 2-2 2 2 0 0 1 2 2v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 0 2 2 0 0 1 0 2.83l-.06.06a1.65 1.65 0 0 0-.33 1.82V9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 2 2 2 2 0 0 1-2 2h-.09a1.65 1.65 0 0 0-1.51 1z" />
              </svg>
              Settings
            </button>
          )}
          {canWrite ? (
            <button className="btn btn-primary" onClick={() => setShowForm(!showForm)}>
              {showForm ? 'Cancel' : '+ New Package'}
            </button>
          ) : user ? (
            <span className="text-muted" title="You have read-only access to this project">
              Read-only access
            </span>
          ) : null}
        </div>
      </div>

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

      {showForm && canWrite && (
        <form className="form card" onSubmit={handleCreatePackage}>
          <h3>Create New Package</h3>
          <div className="form-row">
            <div className="form-group">
              <label htmlFor="name">Name</label>
              <input
                id="name"
                type="text"
                value={newPackage.name}
                onChange={(e) => setNewPackage({ ...newPackage, name: e.target.value })}
                placeholder="releases"
                required
              />
            </div>
            <div className="form-group">
              <label htmlFor="format">Format</label>
              <select
                id="format"
                value={newPackage.format}
                onChange={(e) => setNewPackage({ ...newPackage, format: e.target.value })}
              >
                {FORMAT_OPTIONS.map((f) => (
                  <option key={f} value={f}>
                    {f}
                  </option>
                ))}
              </select>
            </div>
          </div>
          <div className="form-group">
            <label htmlFor="description">Description</label>
            <input
              id="description"
              type="text"
              value={newPackage.description}
              onChange={(e) => setNewPackage({ ...newPackage, description: e.target.value })}
              placeholder="Optional description"
            />
          </div>
          <button type="submit" className="btn btn-primary" disabled={creating}>
            {creating ? 'Creating...' : 'Create Package'}
          </button>
        </form>
      )}

      <div className="list-controls">
        <SearchInput
          value={search}
          onChange={handleSearchChange}
          placeholder="Filter packages..."
          className="list-controls__search"
        />
        <select
          className="list-controls__select"
          value={format}
          onChange={(e) => handleFormatChange(e.target.value)}
        >
          <option value="">All formats</option>
          {FORMAT_OPTIONS.map((f) => (
            <option key={f} value={f}>
              {f}
            </option>
          ))}
        </select>
      </div>

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

      <div className="data-table--responsive">
        <DataTable
          data={packages}
          keyExtractor={(pkg) => pkg.id}
          onRowClick={(pkg) => navigate(`/project/${projectName}/${pkg.name}`)}
          onSort={handleSortChange}
          sortKey={sort}
          sortOrder={order}
          emptyMessage={
            hasActiveFilters
              ? 'No packages match your filters. Try adjusting your search.'
              : 'No packages yet. Create your first package to start uploading artifacts!'
          }
          columns={[
            {
              key: 'name',
              header: 'Name',
              sortable: true,
              render: (pkg) => <span className="cell-name">{pkg.name}</span>,
            },
            {
              key: 'description',
              header: 'Description',
              className: 'cell-description',
              render: (pkg) => pkg.description || '—',
            },
            {
              key: 'format',
              header: 'Format',
              render: (pkg) => <Badge variant="default">{pkg.format}</Badge>,
            },
            {
              key: 'tag_count',
              header: 'Tags',
              render: (pkg) => pkg.tag_count ?? '—',
            },
            {
              key: 'artifact_count',
              header: 'Artifacts',
              render: (pkg) => pkg.artifact_count ?? '—',
            },
            {
              key: 'total_size',
              header: 'Size',
              render: (pkg) =>
                pkg.total_size !== undefined && pkg.total_size > 0 ? formatBytes(pkg.total_size) : '—',
            },
            {
              key: 'latest_tag',
              header: 'Latest',
              render: (pkg) =>
                pkg.latest_tag ? <strong style={{ color: 'var(--accent-primary)' }}>{pkg.latest_tag}</strong> : '—',
            },
            {
              key: 'created_at',
              header: 'Created',
              sortable: true,
              className: 'cell-date',
              render: (pkg) => new Date(pkg.created_at).toLocaleDateString(),
            },
          ]}
        />
      </div>

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

export default ProjectPage;
