import { getDb } from '../database/database';
import { localTimestamp, formatLocalDate, formatLocalDateTime } from '../utils/time';

export interface CloudConfig {
  id: number;
  cloud_type: string;
  cookie?: string;
  nickname?: string;
  is_active: number;
  storage_used?: string;
  storage_total?: string;
  checkin_status: string;       // 'none'|'success'|'failed'|'pending'|'skipped'
  last_checkin_at?: string;
  checkin_message?: string;
  consecutive_failures: number;
  last_used_at?: string;
  total_saves: number;
  created_at: string;
  updated_at: string;
  verification_status?: string;
}

// ── Config CRUD ──────────────────────────────────────────────────

export function getCloudConfigs(): CloudConfig[] {
  const db = getDb();
  return db.prepare(
    `SELECT id, cloud_type, cookie, nickname, is_active, storage_used, storage_total,
            checkin_status, last_checkin_at, checkin_message, consecutive_failures,
            last_used_at, total_saves, created_at, updated_at, verification_status
     FROM cloud_configs ORDER BY id ASC`
  ).all() as CloudConfig[];
}

export function getAvailableClouds(): CloudConfig[] {
  const db = getDb();
  return db.prepare(
    `SELECT id, cloud_type, nickname, is_active, storage_used, storage_total,
            checkin_status, last_checkin_at, checkin_message, consecutive_failures,
            last_used_at, total_saves, created_at, updated_at
     FROM cloud_configs WHERE is_active = 1 ORDER BY id ASC`
  ).all() as CloudConfig[];
}

/** Returns the first active config matching the given cloud type. */
export function getCloudConfigByType(cloudType: string): CloudConfig | undefined {
  const db = getDb();
  return db.prepare(
    `SELECT id, cloud_type, cookie, nickname, is_active, storage_used, storage_total,
            checkin_status, last_checkin_at, checkin_message, consecutive_failures,
            last_used_at, total_saves, created_at, updated_at, verification_status
     FROM cloud_configs WHERE cloud_type = ? AND is_active = 1
     ORDER BY id ASC LIMIT 1`
  ).get(cloudType) as CloudConfig | undefined;
}

export function getCloudConfigById(id: number): CloudConfig | undefined {
  const db = getDb();
  return db.prepare(
    `SELECT id, cloud_type, cookie, nickname, is_active, storage_used, storage_total,
            checkin_status, last_checkin_at, checkin_message, consecutive_failures,
            last_used_at, total_saves, created_at, updated_at, verification_status
     FROM cloud_configs WHERE id = ?`
  ).get(id) as CloudConfig | undefined;
}

/** Returns all active cloud configs (used by save flow for cloud type switching). */
export function getActiveCloudConfigs(): CloudConfig[] {
  const db = getDb();
  return db.prepare(
    `SELECT id, cloud_type, cookie, nickname, is_active, storage_used, storage_total,
            checkin_status, last_checkin_at, checkin_message, consecutive_failures,
            last_used_at, total_saves, created_at, updated_at
     FROM cloud_configs WHERE is_active = 1
     ORDER BY cloud_type ASC, id ASC`
  ).all() as CloudConfig[];
}

export function saveCloudConfig(data: {
  id?: number;
  cloud_type: string;
  cookie?: string;
  nickname?: string;
  is_active?: number;
  storage_used?: string;
  storage_total?: string;
}): CloudConfig {
  const db = getDb();

  if (data.id) {
    db.prepare(
      `UPDATE cloud_configs SET
       cloud_type = COALESCE(?, cloud_type),
       cookie = COALESCE(?, cookie),
       nickname = COALESCE(?, nickname),
       is_active = COALESCE(?, is_active),
       storage_used = COALESCE(?, storage_used),
       storage_total = COALESCE(?, storage_total),
       consecutive_failures = 0,
       updated_at = ?
       WHERE id = ?`
    ).run(data.cloud_type, data.cookie || null, data.nickname || null, data.is_active ?? 1, data.storage_used || null, data.storage_total || null, localTimestamp(), data.id);
  } else {
    const existing = db.prepare(
      'SELECT id, nickname FROM cloud_configs WHERE cloud_type = ? AND is_active = 1 LIMIT 1'
    ).get(data.cloud_type) as any;
    if (existing) {
      db.prepare(
        `UPDATE cloud_configs SET
         cookie = COALESCE(?, cookie),
         nickname = COALESCE(?, nickname),
         is_active = COALESCE(?, is_active),
         storage_used = COALESCE(?, storage_used),
         storage_total = COALESCE(?, storage_total),
         consecutive_failures = 0,
         updated_at = ?
         WHERE id = ?`
      ).run(data.cookie || null, data.nickname || null, data.is_active ?? 1, data.storage_used || null, data.storage_total || null, localTimestamp(), existing.id);
    } else {
      db.prepare(
        'INSERT INTO cloud_configs (cloud_type, cookie, nickname, is_active, storage_used, storage_total, consecutive_failures) VALUES (?, ?, ?, ?, ?, ?, 0)'
      ).run(data.cloud_type, data.cookie || null, data.nickname || null, data.is_active ?? 1, data.storage_used || null, data.storage_total || null);
    }
  }

  const savedId = data.id || (db.prepare('SELECT last_insert_rowid() as id').get() as any).id;
  return db.prepare(
    `SELECT id, cloud_type, cookie, nickname, is_active, storage_used, storage_total,
            checkin_status, last_checkin_at, checkin_message, consecutive_failures,
            last_used_at, total_saves, created_at, updated_at
     FROM cloud_configs WHERE id = ?`
  ).get(savedId) as CloudConfig;
}

export function deleteCloudConfig(id: number): boolean {
  const db = getDb();
  const result = db.prepare('DELETE FROM cloud_configs WHERE id = ?').run(id);
  return result.changes > 0;
}

// ── Cookie Validation ────────────────────────────────────────────

async function fetchQuarkNickname(cookie: string): Promise<string | null> {
  const MAX_RETRIES = 2;
  for (let attempt = 0; attempt <= MAX_RETRIES; attempt++) {
    try {
      const response = await fetch('https://pan.quark.cn/account/info', {
        headers: {
          'Cookie': cookie,
          'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36',
          'Referer': 'https://pan.quark.cn/',
        },
        signal: AbortSignal.timeout(15000),
      });
      if (!response.ok) return null;
      const data = await response.json() as any;
      if (data?.data?.nickname) return data.data.nickname;
    } catch {
      if (attempt < MAX_RETRIES) {
        await new Promise(r => setTimeout(r, 1500));
        continue;
      }
    }
  }
  return null;
}

export async function testCloudConnection(id: number): Promise<{
  success: boolean;
  message: string;
  nickname?: string;
  storage_used?: string;
  storage_total?: string;
}> {
  const config = getCloudConfigById(id);
  if (!config) {
    return { success: false, message: 'Cloud config not found' };
  }

  if (!config.cookie) {
    return { success: false, message: 'Cookie not configured' };
  }

  try {
    let valid = false;
    let nickname = '';
    let storageUsed = config.storage_used || '';
    let storageTotal = config.storage_total || '';

    if (config.cloud_type === 'baidu') {
      const { BaiduDriver } = require('./drivers/baidu.driver');
      const driver = new BaiduDriver({ cookie: config.cookie, nickname: config.nickname });
      valid = await driver.validate();
      if (valid) {
        const info = await driver.getUserInfo();
        if (info) {
          nickname = config.nickname || info.nickname || '百度网盘';
          const fmt = (b: number) => b >= 1024**3 ? (b/1024**3).toFixed(2)+' GB' : (b/1024**2).toFixed(2)+' MB';
          storageUsed = fmt(info.usedBytes);
          storageTotal = fmt(info.totalBytes);
        }
      }
    } else {
      const { QuarkDriver } = require('./drivers/quark.driver');
      const driver = new QuarkDriver({ cookie: config.cookie, nickname: config.nickname });
      valid = await driver.validate();
      if (valid) {
        nickname = config.nickname || (await fetchQuarkNickname(config.cookie)) || '夸克网盘';
        const storage = await driver.getStorageInfoQuick();
        storageTotal = (storage.total !== '-' && storage.total !== '0 B') ? storage.total : (config.storage_total || '');
      }
    }

    const db = getDb();
    if (!valid) {
      db.prepare(
        `UPDATE cloud_configs SET verification_status = 'invalid', updated_at = ? WHERE id = ?`
      ).run(localTimestamp(), id);
      return { success: false, message: '连接失败：Cookie 无效或已过期，或网络暂时异常' };
    }

    db.prepare(
      `UPDATE cloud_configs SET nickname = ?, storage_total = ?, storage_used = ?, is_active = 1, verification_status = 'valid', updated_at = ? WHERE id = ?`
    ).run(nickname, storageTotal, storageUsed, localTimestamp(), id);

    return {
      success: true,
      message: '连接成功',
      nickname,
      storage_used: storageUsed,
      storage_total: storageTotal,
    };
  } catch (err: any) {
    try {
      const db = getDb();
      db.prepare(
        `UPDATE cloud_configs SET verification_status = 'invalid', updated_at = ? WHERE id = ?`
      ).run(localTimestamp(), id);
    } catch {}
    return { success: false, message: `连接失败：${err.message || '未知错误'}` };
  }
}

export async function testCloudConnectionWithCookie(cloudType: string, cookie: string): Promise<{
  success: boolean;
  message: string;
  nickname?: string;
  storage_used?: string;
  storage_total?: string;
}> {
  try {
    const { QuarkDriver } = require('./drivers/quark.driver');
    const driver = new QuarkDriver({ cookie, nickname: '' });
    const valid = await driver.validate();
    if (!valid) {
      return { success: false, message: '连接失败：Cookie 无效或已过期' };
    }
    const nickname = (await fetchQuarkNickname(cookie)) || cloudType;
    const storage = await driver.getStorageInfo();
    return {
      success: true,
      message: '连接成功',
      nickname,
      storage_used: storage.used,
      storage_total: storage.total,
    };
  } catch (err: any) {
    return { success: false, message: `连接失败：${err.message || '未知错误'}` };
  }
}

// ── Unified Credential Validation ─────────────────────────────────

export interface CredentialValidationResult {
  valid: boolean;
  config?: CloudConfig;
  errorCode?: string;
  message: string;
}

/**
 * Get and validate a credential for the given cloud type.
 * 
 * This is the unified entry point for all save/transfer operations.
 * It handles:
 *   1. Finding an active config with < 5 consecutive failures (round-robin)
 *   2. Validating cookie freshness via driver.validate()
 *   3. Returning structured result with error codes
 * 
 * Reference: search-ucmao get_and_validate_credential() pattern.
 */
export async function getAndValidateCredential(cloudType: string): Promise<CredentialValidationResult> {
  const db = getDb();

  const config = db.prepare(
    `SELECT * FROM cloud_configs
     WHERE cloud_type = ? AND is_active = 1
     AND consecutive_failures < 5
     ORDER BY last_used_at ASC NULLS FIRST
     LIMIT 1`
  ).get(cloudType) as CloudConfig | undefined;

  if (!config) {
    return {
      valid: false,
      errorCode: 'NO_AVAILABLE_DRIVE',
      message: `Cloud type "${cloudType}" is not configured or no available drives`,
    };
  }

  if (!config.cookie) {
    return {
      valid: false,
      errorCode: 'COOKIE_MISSING',
      message: `Cookie not configured for ${cloudType} drive #${config.id}`,
    };
  }

  try {
    let cookieValid = false;
    if (cloudType === 'baidu') {
      const { BaiduDriver } = require('./drivers/baidu.driver');
      const driver = new BaiduDriver({ cookie: config.cookie, nickname: config.nickname });
      cookieValid = await driver.validate();
    } else {
      const { QuarkDriver } = require('./drivers/quark.driver');
      const driver = new QuarkDriver({ cookie: config.cookie, nickname: config.nickname });
      cookieValid = await driver.validate();
    }

    if (!cookieValid) {
      db.prepare(
        `UPDATE cloud_configs SET verification_status = 'invalid', updated_at = ? WHERE id = ?`
      ).run(localTimestamp(), config.id);
      return {
        valid: false,
        errorCode: 'COOKIE_EXPIRED',
        message: `Cookie expired or invalid for ${cloudType} drive #${config.id}`,
      };
    }

    return {
      valid: true,
      config,
      message: 'ok',
    };
  } catch (err: any) {
    return {
      valid: false,
      errorCode: 'VALIDATION_ERROR',
      message: `Credential validation failed: ${err.message}`,
    };
  }
}
