import {
  AssessmentProfile,
  AssessmentRecord,
  MindScopeBackup,
} from '@/lib/assessment-types';

const DB_NAME = 'mindscope';
const DB_VERSION = 1;
const PROFILE_STORE = 'profiles';
const RECORD_STORE = 'records';
const ACTIVE_PROFILE_KEY = 'mindscope_active_profile';

function createId(prefix: string) {
  return `${prefix}_${Date.now()}_${crypto.randomUUID()}`;
}

function openDatabase(): Promise<IDBDatabase> {
  return new Promise((resolve, reject) => {
    const request = indexedDB.open(DB_NAME, DB_VERSION);
    request.onerror = () => reject(request.error);
    request.onsuccess = () => resolve(request.result);
    request.onupgradeneeded = () => {
      const db = request.result;
      if (!db.objectStoreNames.contains(PROFILE_STORE)) {
        db.createObjectStore(PROFILE_STORE, { keyPath: 'id' });
      }
      if (!db.objectStoreNames.contains(RECORD_STORE)) {
        const records = db.createObjectStore(RECORD_STORE, { keyPath: 'id' });
        records.createIndex('profileId', 'profileId');
        records.createIndex('questionnaireId', 'questionnaireId');
      }
    };
  });
}

function requestResult<T>(request: IDBRequest<T>): Promise<T> {
  return new Promise((resolve, reject) => {
    request.onsuccess = () => resolve(request.result);
    request.onerror = () => reject(request.error);
  });
}

export function getActiveProfileId() {
  return localStorage.getItem(ACTIVE_PROFILE_KEY);
}

export function setActiveProfileId(profileId: string) {
  localStorage.setItem(ACTIVE_PROFILE_KEY, profileId);
  window.dispatchEvent(new CustomEvent('mindscope-profile-change'));
}

export async function getProfiles(): Promise<AssessmentProfile[]> {
  const db = await openDatabase();
  const profiles = await requestResult(
    db.transaction(PROFILE_STORE, 'readonly').objectStore(PROFILE_STORE).getAll(),
  );
  db.close();
  return profiles.sort((a, b) => a.createdAt.localeCompare(b.createdAt));
}

export async function createProfile(name: string): Promise<AssessmentProfile> {
  const now = new Date().toISOString();
  const profile: AssessmentProfile = {
    id: createId('profile'),
    name: name.trim(),
    createdAt: now,
    updatedAt: now,
  };
  const db = await openDatabase();
  await requestResult(
    db.transaction(PROFILE_STORE, 'readwrite').objectStore(PROFILE_STORE).add(profile),
  );
  db.close();
  return profile;
}

export async function ensureActiveProfile(): Promise<AssessmentProfile> {
  const profiles = await getProfiles();
  const activeId = getActiveProfileId();
  const active = profiles.find((profile) => profile.id === activeId);
  if (active) return active;
  const profile = profiles[0] || (await createProfile('我'));
  setActiveProfileId(profile.id);
  return profile;
}

export async function renameProfile(profileId: string, name: string) {
  const db = await openDatabase();
  const store = db.transaction(PROFILE_STORE, 'readwrite').objectStore(PROFILE_STORE);
  const profile = await requestResult(store.get(profileId));
  if (profile) {
    await requestResult(
      store.put({ ...profile, name: name.trim(), updatedAt: new Date().toISOString() }),
    );
  }
  db.close();
}

export async function deleteProfile(profileId: string) {
  const db = await openDatabase();
  const transaction = db.transaction([PROFILE_STORE, RECORD_STORE], 'readwrite');
  transaction.objectStore(PROFILE_STORE).delete(profileId);
  const index = transaction.objectStore(RECORD_STORE).index('profileId');
  const recordKeys = await requestResult(index.getAllKeys(profileId));
  recordKeys.forEach((key) => transaction.objectStore(RECORD_STORE).delete(key));
  await new Promise<void>((resolve, reject) => {
    transaction.oncomplete = () => resolve();
    transaction.onerror = () => reject(transaction.error);
  });
  db.close();
}

export async function addAssessmentRecord(
  record: Omit<AssessmentRecord, 'id'>,
): Promise<AssessmentRecord> {
  const completeRecord = { ...record, id: createId('record') };
  const db = await openDatabase();
  await requestResult(
    db.transaction(RECORD_STORE, 'readwrite').objectStore(RECORD_STORE).add(completeRecord),
  );
  db.close();
  return completeRecord;
}

export async function updateRecordAnalysis(recordId: string, analysisText: string) {
  const db = await openDatabase();
  const store = db.transaction(RECORD_STORE, 'readwrite').objectStore(RECORD_STORE);
  const record = await requestResult(store.get(recordId));
  if (record && record.analysisText !== analysisText) {
    await requestResult(store.put({ ...record, analysisText }));
  }
  db.close();
}

export async function getRecords(profileId?: string): Promise<AssessmentRecord[]> {
  const db = await openDatabase();
  const store = db.transaction(RECORD_STORE, 'readonly').objectStore(RECORD_STORE);
  const records = profileId
    ? await requestResult(store.index('profileId').getAll(profileId))
    : await requestResult(store.getAll());
  db.close();
  return records.sort((a, b) => b.completedAt.localeCompare(a.completedAt));
}

export async function deleteRecord(recordId: string) {
  const db = await openDatabase();
  await requestResult(
    db.transaction(RECORD_STORE, 'readwrite').objectStore(RECORD_STORE).delete(recordId),
  );
  db.close();
}

export async function exportBackup(): Promise<MindScopeBackup> {
  return {
    format: 'mindscope-backup',
    version: 1,
    exportedAt: new Date().toISOString(),
    profiles: await getProfiles(),
    records: await getRecords(),
  };
}

export async function importBackup(backup: MindScopeBackup) {
  if (backup.format !== 'mindscope-backup' || backup.version !== 1) {
    throw new Error('不支持的备份格式');
  }
  const db = await openDatabase();
  const transaction = db.transaction([PROFILE_STORE, RECORD_STORE], 'readwrite');
  backup.profiles.forEach((profile) => transaction.objectStore(PROFILE_STORE).put(profile));
  backup.records.forEach((record) => transaction.objectStore(RECORD_STORE).put(record));
  await new Promise<void>((resolve, reject) => {
    transaction.oncomplete = () => resolve();
    transaction.onerror = () => reject(transaction.error);
  });
  db.close();
}

export async function clearAllAssessmentData() {
  const db = await openDatabase();
  const transaction = db.transaction([PROFILE_STORE, RECORD_STORE], 'readwrite');
  transaction.objectStore(PROFILE_STORE).clear();
  transaction.objectStore(RECORD_STORE).clear();
  await new Promise<void>((resolve, reject) => {
    transaction.oncomplete = () => resolve();
    transaction.onerror = () => reject(transaction.error);
  });
  db.close();
  localStorage.removeItem(ACTIVE_PROFILE_KEY);
}
