import { reactive, ref } from 'vue';

import { apiGet, ensureMesApiAvailable } from '../../core/api.js';
import { exportCsv } from '../utils/csv.js';
import { normalizeText, parseDateTime, uniqueValues, formatDateTime } from '../utils/values.js';

const LOT_SUB_TABS = Object.freeze([
  'history',
  'materials',
  'rejects',
  'holds',
  'jobs',
]);

const ASSOCIATION_TABS = new Set(['materials', 'rejects', 'holds', 'jobs']);

const EXPORT_TYPE_MAP = Object.freeze({
  history: 'lot_history',
  materials: 'lot_materials',
  rejects: 'lot_rejects',
  holds: 'lot_holds',
  jobs: 'lot_jobs',
});

function emptyTabFlags() {
  return {
    history: false,
    materials: false,
    rejects: false,
    holds: false,
    jobs: false,
  };
}

function emptyTabErrors() {
  return {
    workcenterGroups: '',
    history: '',
    materials: '',
    rejects: '',
    holds: '',
    jobs: '',
  };
}

function emptyAssociations() {
  return {
    materials: [],
    rejects: [],
    holds: [],
    jobs: [],
  };
}

function normalizeSubTab(value) {
  const tab = normalizeText(value).toLowerCase();
  return LOT_SUB_TABS.includes(tab) ? tab : 'history';
}

function resolveTimeRangeFromHistory(rows) {
  if (!Array.isArray(rows) || rows.length === 0) {
    return null;
  }

  let minTrackIn = null;
  let maxTrackOut = null;

  rows.forEach((row) => {
    const trackIn = parseDateTime(row?.TRACKINTIMESTAMP || row?.TRACKINTIME);
    const trackOut = parseDateTime(row?.TRACKOUTTIMESTAMP || row?.TRACKOUTTIME);

    if (trackIn && (!minTrackIn || trackIn < minTrackIn)) {
      minTrackIn = trackIn;
    }

    if (trackOut && (!maxTrackOut || trackOut > maxTrackOut)) {
      maxTrackOut = trackOut;
    }

    if (!maxTrackOut && trackIn && (!maxTrackOut || trackIn > maxTrackOut)) {
      maxTrackOut = trackIn;
    }
  });

  if (!minTrackIn || !maxTrackOut) {
    return null;
  }

  return {
    time_start: formatDateTime(minTrackIn),
    time_end: formatDateTime(maxTrackOut),
  };
}

function resolveEquipmentIdFromHistory(rows) {
  if (!Array.isArray(rows) || rows.length === 0) {
    return '';
  }

  for (const row of rows) {
    const equipmentId = normalizeText(row?.EQUIPMENTID || row?.RESOURCEID);
    if (equipmentId) {
      return equipmentId;
    }
  }

  return '';
}

export function useLotDetail(initial = {}) {
  ensureMesApiAvailable();

  const selectedContainerId = ref(normalizeText(initial.selectedContainerId));
  const selectedContainerIds = ref(
    initial.selectedContainerId ? [normalizeText(initial.selectedContainerId)] : [],
  );
  const activeSubTab = ref(normalizeSubTab(initial.activeSubTab));

  const workcenterGroups = ref([]);
  const selectedWorkcenterGroups = ref(uniqueValues(initial.workcenterGroups || []));

  const historyRows = ref([]);
  const associationRows = reactive(emptyAssociations());

  const loading = reactive({
    workcenterGroups: false,
    history: false,
    materials: false,
    rejects: false,
    holds: false,
    jobs: false,
  });

  const loaded = reactive(emptyTabFlags());
  const exporting = reactive(emptyTabFlags());
  const errors = reactive(emptyTabErrors());

  function clearTabData() {
    historyRows.value = [];
    const nextAssociations = emptyAssociations();
    Object.keys(nextAssociations).forEach((key) => {
      associationRows[key] = nextAssociations[key];
    });

    const nextLoaded = emptyTabFlags();
    Object.keys(nextLoaded).forEach((key) => {
      loaded[key] = nextLoaded[key];
      exporting[key] = false;
      errors[key] = '';
    });
  }

  function getActiveCids() {
    if (selectedContainerIds.value.length > 0) {
      return selectedContainerIds.value;
    }
    const single = selectedContainerId.value;
    return single ? [single] : [];
  }

  async function loadWorkcenterGroups() {
    loading.workcenterGroups = true;
    errors.workcenterGroups = '';

    try {
      const payload = await apiGet('/api/query-tool/workcenter-groups', {
        timeout: 60000,
        silent: true,
      });

      workcenterGroups.value = Array.isArray(payload?.data) ? payload.data : [];
      return true;
    } catch (error) {
      errors.workcenterGroups = error?.message || '載入站點群組失敗';
      workcenterGroups.value = [];
      return false;
    } finally {
      loading.workcenterGroups = false;
    }
  }

  async function loadHistory({ force = false } = {}) {
    const cids = getActiveCids();
    if (cids.length === 0) {
      return false;
    }

    if (!force && loaded.history) {
      return true;
    }

    loading.history = true;
    errors.history = '';

    try {
      const params = new URLSearchParams();
      // Batch mode: send all CIDs in one request
      if (cids.length > 1) {
        params.set('container_ids', cids.join(','));
      } else {
        params.set('container_id', cids[0]);
      }
      if (selectedWorkcenterGroups.value.length > 0) {
        params.set('workcenter_groups', selectedWorkcenterGroups.value.join(','));
      }

      const payload = await apiGet(`/api/query-tool/lot-history?${params.toString()}`, {
        timeout: 120000,
        silent: true,
      });

      historyRows.value = Array.isArray(payload?.data) ? payload.data : [];
      loaded.history = true;
      return true;
    } catch (error) {
      errors.history = error?.message || '載入 LOT 歷程失敗';
      historyRows.value = [];
      return false;
    } finally {
      loading.history = false;
    }
  }

  async function loadAssociation(tab, { force = false, silentError = false } = {}) {
    const associationType = normalizeSubTab(tab);
    if (!ASSOCIATION_TABS.has(associationType)) {
      return false;
    }

    const cids = getActiveCids();
    if (cids.length === 0) {
      return false;
    }

    if (!force && loaded[associationType]) {
      return true;
    }

    loading[associationType] = true;
    if (!silentError) {
      errors[associationType] = '';
    }

    try {
      if (associationType === 'jobs') {
        // Jobs derive equipment/time from merged history — use first CID as anchor
        if (historyRows.value.length === 0) {
          await loadHistory();
        }

        const equipmentId = resolveEquipmentIdFromHistory(historyRows.value);
        const timeRange = resolveTimeRangeFromHistory(historyRows.value);

        if (!equipmentId || !timeRange?.time_start || !timeRange?.time_end) {
          throw new Error('無法從 LOT 歷程推導 JOB 查詢條件，請先確認歷程資料');
        }

        const params = new URLSearchParams();
        params.set('container_id', cids[0]);
        params.set('type', associationType);
        params.set('equipment_id', equipmentId);
        params.set('time_start', timeRange.time_start);
        params.set('time_end', timeRange.time_end);

        const payload = await apiGet(`/api/query-tool/lot-associations?${params.toString()}`, {
          timeout: 120000,
          silent: true,
        });

        associationRows[associationType] = Array.isArray(payload?.data) ? payload.data : [];
      } else {
        // Non-jobs tabs: batch all CIDs into a single request
        const params = new URLSearchParams();
        if (cids.length > 1) {
          params.set('container_ids', cids.join(','));
        } else {
          params.set('container_id', cids[0]);
        }
        params.set('type', associationType);

        const payload = await apiGet(`/api/query-tool/lot-associations?${params.toString()}`, {
          timeout: 120000,
          silent: true,
        });

        associationRows[associationType] = Array.isArray(payload?.data) ? payload.data : [];
      }

      loaded[associationType] = true;
      return true;
    } catch (error) {
      associationRows[associationType] = [];
      if (!silentError) {
        errors[associationType] = error?.message || '載入關聯資料失敗';
      }
      return false;
    } finally {
      loading[associationType] = false;
    }
  }

  async function ensureActiveSubTabData() {
    if (activeSubTab.value === 'history') {
      const historyOk = await loadHistory();
      if (historyOk) {
        // History timeline uses hold/material events as marker sources.
        await Promise.allSettled([
          loadAssociation('holds', { silentError: true }),
          loadAssociation('materials', { silentError: true }),
        ]);
      }
      return historyOk;
    }

    return loadAssociation(activeSubTab.value);
  }

  async function setActiveSubTab(tab) {
    activeSubTab.value = normalizeSubTab(tab);
    return ensureActiveSubTabData();
  }

  async function setSelectedContainerId(containerId) {
    const nextId = normalizeText(containerId);
    selectedContainerIds.value = nextId ? [nextId] : [];

    if (nextId === selectedContainerId.value) {
      return ensureActiveSubTabData();
    }

    selectedContainerId.value = nextId;
    clearTabData();

    if (!nextId) {
      return false;
    }

    return ensureActiveSubTabData();
  }

  async function setSelectedContainerIds(cids) {
    const normalized = uniqueValues(
      (Array.isArray(cids) ? cids : []).map(normalizeText).filter(Boolean),
    );
    selectedContainerIds.value = normalized;
    selectedContainerId.value = normalized[0] || '';
    clearTabData();

    if (normalized.length === 0) {
      return false;
    }

    return ensureActiveSubTabData();
  }

  async function setSelectedWorkcenterGroups(groups) {
    selectedWorkcenterGroups.value = uniqueValues(groups || []);

    if (!selectedContainerId.value) {
      return false;
    }

    loaded.history = false;
    return loadHistory({ force: true });
  }

  function getRowsByTab(tab) {
    const normalized = normalizeSubTab(tab);
    if (normalized === 'history') {
      return historyRows.value;
    }
    if (!ASSOCIATION_TABS.has(normalized)) {
      return [];
    }
    return associationRows[normalized] || [];
  }

  async function exportSubTab(tab) {
    const normalized = normalizeSubTab(tab);
    const exportType = EXPORT_TYPE_MAP[normalized];
    const cids = getActiveCids();

    if (!exportType || cids.length === 0) {
      return false;
    }

    exporting[normalized] = true;
    errors[normalized] = '';

    try {
      const params = {
        container_ids: cids,
      };

      if (normalized === 'jobs') {
        if (historyRows.value.length === 0) {
          await loadHistory();
        }
        const equipmentId = resolveEquipmentIdFromHistory(historyRows.value);
        const timeRange = resolveTimeRangeFromHistory(historyRows.value);
        if (!equipmentId || !timeRange?.time_start || !timeRange?.time_end) {
          throw new Error('無法取得 JOB 匯出所需條件');
        }
        params.equipment_id = equipmentId;
        params.time_start = timeRange.time_start;
        params.time_end = timeRange.time_end;
      }

      await exportCsv({
        exportType,
        params,
      });

      return true;
    } catch (error) {
      errors[normalized] = error?.message || '匯出失敗';
      return false;
    } finally {
      exporting[normalized] = false;
    }
  }

  return {
    lotSubTabs: LOT_SUB_TABS,
    selectedContainerId,
    selectedContainerIds,
    activeSubTab,
    workcenterGroups,
    selectedWorkcenterGroups,
    historyRows,
    associationRows,
    loading,
    loaded,
    exporting,
    errors,
    loadWorkcenterGroups,
    loadHistory,
    loadAssociation,
    ensureActiveSubTabData,
    setActiveSubTab,
    setSelectedContainerId,
    setSelectedContainerIds,
    setSelectedWorkcenterGroups,
    getRowsByTab,
    exportSubTab,
    clearTabData,
  };
}
