import type { SubsonicSong } from '@/api/subsonicTypes';
import React, { useState, useCallback, useMemo } from 'react';
import { useTranslation } from 'react-i18next';
import { useDeviceSyncStore, DeviceSyncSource } from '@/features/deviceSync/store/deviceSyncStore';
import { useDeviceSyncJobStore } from '@/features/deviceSync/store/deviceSyncJobStore';

import {
  type SourceTab,
} from '@/features/deviceSync/utils/deviceSyncHelpers';
import { useDeviceSyncDrives } from '@/features/deviceSync/hooks/useDeviceSyncDrives';
import { useDeviceSyncSourceStatuses } from '@/features/deviceSync/hooks/useDeviceSyncSourceStatuses';
import { useDeviceSyncBrowser } from '@/features/deviceSync/hooks/useDeviceSyncBrowser';
import { useDeviceSyncDeviceScan } from '@/features/deviceSync/hooks/useDeviceSyncDeviceScan';
import { useDeviceSyncJobEvents } from '@/features/deviceSync/hooks/useDeviceSyncJobEvents';
import {
  runDeviceSyncMigrationPreview,
  runDeviceSyncMigrationExecute,
  type MigrationPhase, type MigrationPair, type MigrationResult,
} from '@/features/deviceSync/utils/runDeviceSyncMigration';
import {
  runDeviceSyncSummaryPrompt,
  runDeviceSyncExecute,
  type SyncDelta,
} from '@/features/deviceSync/utils/runDeviceSyncExecution';
import { runDeviceSyncChooseFolder } from '@/features/deviceSync/utils/runDeviceSyncChooseFolder';
import DeviceSyncHeader from '@/features/deviceSync/components/DeviceSyncHeader';
import DeviceSyncPreSyncModal from '@/features/deviceSync/components/DeviceSyncPreSyncModal';
import DeviceSyncMigrationModal from '@/features/deviceSync/components/DeviceSyncMigrationModal';
import DeviceSyncBrowserPanel from '@/features/deviceSync/components/DeviceSyncBrowserPanel';
import DeviceSyncDevicePanel from '@/features/deviceSync/components/DeviceSyncDevicePanel';

// ─── component ───────────────────────────────────────────────────────────────

export default function DeviceSync() {
  const { t } = useTranslation();

  const targetDir        = useDeviceSyncStore(s => s.targetDir);
  const sources          = useDeviceSyncStore(s => s.sources);
  const checkedIds       = useDeviceSyncStore(s => s.checkedIds);
  const pendingDeletion  = useDeviceSyncStore(s => s.pendingDeletion);
  const deviceFilePaths  = useDeviceSyncStore(s => s.deviceFilePaths);
  const scanning         = useDeviceSyncStore(s => s.scanning);
  const {
    setTargetDir, addSource, removeSource,
    toggleChecked, setCheckedIds, markForDeletion,
    unmarkDeletion, removeSources,
  } = useDeviceSyncStore.getState();

  const jobStatus = useDeviceSyncJobStore(s => s.status);
  const jobDone   = useDeviceSyncJobStore(s => s.done);
  const jobSkip   = useDeviceSyncJobStore(s => s.skipped);
  const jobFail   = useDeviceSyncJobStore(s => s.failed);
  const jobTotal  = useDeviceSyncJobStore(s => s.total);

  const [activeTab, setActiveTab]           = useState<SourceTab>('albums');
  const [search, setSearch]                 = useState('');
  // ─── Removable drive detection ──────────────────────────────────────────
  const { drives, drivesLoading, activeDrive, driveDetected, refreshDrives } =
    useDeviceSyncDrives(targetDir);

  const [preSyncOpen, setPreSyncOpen] = useState(false);
  const [preSyncLoading, setPreSyncLoading] = useState(false);
  const [syncDelta, setSyncDelta] = useState<SyncDelta>({ addBytes: 0, addCount: 0, delBytes: 0, delCount: 0, availableBytes: 0, tracks: [] as SubsonicSong[] });

  // ─── Migration (rename existing files into the fixed scheme) ────────────
  const [migrationPhase, setMigrationPhase] = useState<MigrationPhase>('closed');
  const [migrationOldTemplate, setMigrationOldTemplate] = useState<string>('');
  const [migrationPairs, setMigrationPairs] = useState<MigrationPair[]>([]);
  const [migrationCollisions, setMigrationCollisions] = useState<MigrationPair[]>([]);
  const [migrationUnchanged, setMigrationUnchanged] = useState(0);
  const [migrationResult, setMigrationResult] = useState<MigrationResult | null>(null);

  const isRunning = jobStatus === 'running';

  // ─── Device scan + manifest auto-import ─────────────────────────────────
  const { scanDevice } = useDeviceSyncDeviceScan(targetDir, sources.length, driveDetected, t);

  // Source status (path map + derived synced/pending/deletion)
  const { sourcePathsMap, sourceStatuses } = useDeviceSyncSourceStatuses(
    targetDir, sources, pendingDeletion, deviceFilePaths,
  );

  // ─── Desired State / Diff Logic ─────────────────────────────────────────

  const handleToggleSource = useCallback((source: DeviceSyncSource) => {
    const isSelected = sources.some(s => s.id === source.id);
    const isPendingDeletion = pendingDeletion.includes(source.id);
    const isActuallySelected = isSelected && !isPendingDeletion;

    if (isActuallySelected) {
      // User initiated a DE-SELECTION. Diff check against target device
      const isSynced = sourceStatuses.get(source.id) === 'synced';
      const pathsOnDisk = sourcePathsMap.get(source.id)?.filter(p => deviceFilePaths.includes(p)).length || 0;
      
      if (pathsOnDisk > 0 || isSynced) {
        // Source currently has physical footprint. Stage for deletion.
        markForDeletion([source.id]);
      } else {
        // Zero physical footprint. Strip safely.
        removeSource(source.id);
      }
    } else {
      // User initiated a SELECTION.
      if (isPendingDeletion) {
        unmarkDeletion(source.id); // Cancel queued red/strikethrough state
      } else if (!isSelected) {
        addSource(source); // Trigger clean pending install state
      }
    }
  }, [sources, pendingDeletion, sourceStatuses, sourcePathsMap, deviceFilePaths, markForDeletion, removeSource, unmarkDeletion, addSource]);

  // ─── Listen for background sync events ──────────────────────────────────
  useDeviceSyncJobEvents(t, scanDevice);

  // Browser (playlists / albums / artists tabs + their loaders + debounced search)
  const {
    playlists, randomAlbums, albumSearchResults, albumSearchLoading,
    artists, loadingBrowser,
    expandedArtistIds, artistAlbumsMap, loadingArtistIds,
    toggleArtistExpand,
  } = useDeviceSyncBrowser(activeTab, search, () => setSearch(''));

  // ─── Migration handlers ─────────────────────────────────────────────────

  const startMigrationPreview = () => runDeviceSyncMigrationPreview({
    targetDir, sources,
    setMigrationPhase, setMigrationResult, setMigrationOldTemplate,
    setMigrationPairs, setMigrationCollisions, setMigrationUnchanged,
  });

  const executeMigration = () => runDeviceSyncMigrationExecute({
    targetDir, sources, migrationPairs,
    setMigrationPhase, setMigrationResult, scanDevice,
  });

  const closeMigration = () => {
    setMigrationPhase('closed');
    setMigrationPairs([]);
    setMigrationCollisions([]);
    setMigrationResult(null);
    setMigrationOldTemplate('');
  };

  const handleChooseFolder = () => runDeviceSyncChooseFolder({ t, setTargetDir, scanDevice });

  // ─── Sync (non-blocking) ────────────────────────────────────────────────

  const promptSyncSummary = () => runDeviceSyncSummaryPrompt({
    targetDir, sources, pendingDeletion, t,
    setPreSyncLoading, setPreSyncOpen, setSyncDelta,
  });

  const handleSyncExecution = () => runDeviceSyncExecute({
    targetDir, sources, pendingDeletion, syncDelta, t,
    setPreSyncOpen, removeSources, scanDevice,
  });

  // ─── Actions ────────────────────────────────────────────────────────────

  const handleMarkCheckedForDeletion = () => {
    if (checkedIds.length === 0) return;
    markForDeletion(checkedIds);
  };

  const allChecked = sources.length > 0 && sources.every(s => checkedIds.includes(s.id));
  const toggleAll  = () => setCheckedIds(allChecked ? [] : sources.map(s => s.id));

  const pendingCount   = Array.from(sourceStatuses.values()).filter(s => s === 'pending').length;
  const syncedCount    = Array.from(sourceStatuses.values()).filter(s => s === 'synced').length;
  const deletionCount  = pendingDeletion.length;

  // ─── Dynamic action button label ────────────────────────────────────────
  const actionButtonLabel = useMemo(() => {
    if (deletionCount > 0 && pendingCount === 0) return t('deviceSync.actionDelete');
    if (pendingCount > 0 && deletionCount === 0) return t('deviceSync.actionTransfer');
    if (pendingCount > 0 && deletionCount > 0)  return t('deviceSync.actionApplyAll');
    return t('deviceSync.syncButton'); // both zero — button will be disabled
  }, [pendingCount, deletionCount, t]);

  const actionButtonDisabled =
    !targetDir ||
    sources.length === 0 ||
    isRunning ||
    (!driveDetected && !!targetDir) ||
    (pendingCount === 0 && deletionCount === 0);

  return (
    <div className="device-sync-page">

      <DeviceSyncHeader
        targetDir={targetDir}
        setTargetDir={setTargetDir}
        sources={sources}
        drives={drives}
        drivesLoading={drivesLoading}
        activeDrive={activeDrive}
        refreshDrives={refreshDrives}
        scanDevice={scanDevice}
        handleChooseFolder={handleChooseFolder}
        startMigrationPreview={startMigrationPreview}
      />

      {/* ── Main ── */}
      <div className="device-sync-main">

        <DeviceSyncBrowserPanel
          activeTab={activeTab}
          setActiveTab={setActiveTab}
          search={search}
          setSearch={setSearch}
          playlists={playlists}
          randomAlbums={randomAlbums}
          albumSearchResults={albumSearchResults}
          albumSearchLoading={albumSearchLoading}
          artists={artists}
          loadingBrowser={loadingBrowser}
          expandedArtistIds={expandedArtistIds}
          artistAlbumsMap={artistAlbumsMap}
          loadingArtistIds={loadingArtistIds}
          toggleArtistExpand={toggleArtistExpand}
          sources={sources}
          pendingDeletion={pendingDeletion}
          handleToggleSource={handleToggleSource}
        />

        <DeviceSyncDevicePanel
          sources={sources}
          sourceStatuses={sourceStatuses}
          driveDetected={driveDetected}
          scanning={scanning}
          checkedIds={checkedIds}
          toggleChecked={toggleChecked}
          allChecked={allChecked}
          toggleAll={toggleAll}
          syncedCount={syncedCount}
          pendingCount={pendingCount}
          deletionCount={deletionCount}
          isRunning={isRunning}
          actionButtonLabel={actionButtonLabel}
          actionButtonDisabled={actionButtonDisabled}
          promptSyncSummary={promptSyncSummary}
          handleMarkCheckedForDeletion={handleMarkCheckedForDeletion}
          handleToggleSource={handleToggleSource}
          markForDeletion={markForDeletion}
          unmarkDeletion={unmarkDeletion}
          jobStatus={jobStatus}
          jobDone={jobDone}
          jobSkip={jobSkip}
          jobFail={jobFail}
          jobTotal={jobTotal}
        />

      </div>

      <DeviceSyncPreSyncModal
        preSyncOpen={preSyncOpen}
        preSyncLoading={preSyncLoading}
        syncDelta={syncDelta}
        onCancel={() => setPreSyncOpen(false)}
        onProceed={handleSyncExecution}
      />

      <DeviceSyncMigrationModal
        migrationPhase={migrationPhase}
        migrationOldTemplate={migrationOldTemplate}
        migrationPairs={migrationPairs}
        migrationCollisions={migrationCollisions}
        migrationUnchanged={migrationUnchanged}
        migrationResult={migrationResult}
        executeMigration={executeMigration}
        closeMigration={closeMigration}
      />
    </div>
  );
}
