/**
 * Daily Report Service — generates a summary of yesterday's cloud storage activity
 * and sends it through configured notification channels at 08:00 daily.
 */
import { getDb } from '../database/database';
import { getSystemConfig } from '../admin/system-config.service';
import { getCloudConfigs } from '../cloud/credential.service';
import { notify, getGlobalNotifyConfigs, sendToChannels } from '../cloud/notification.service';
import { CLOUD_LABELS } from '../config/cloud-constants';

// ═══════════════════════════════════════════════
// Types
// ═══════════════════════════════════════════════

export interface DailyReportConfig {
  enabled: boolean;
  time: string;          // "HH:mm" e.g. "08:00"
  includeSearch: boolean;
  includeSaves: boolean;
  includeStorage: boolean;
  includeUsers: boolean;
  channels?: string[];   // 指定推送通道，空=全部全局通道
}

export interface DailyReport {
  date: string;
  searchCount: number;
  uniqueSearchers: number;
  saveCounts: { total: number; success: number; fail: number };
  byCloud: Array<{
    cloudType: string;
    nickname: string;
    saves: number;
    successes: number;
    storageUsed: string;
    storageTotal: string;
    isActive: boolean;
  }>;
  uniqueSavers: number;
}

// ═══════════════════════════════════════════════
// Config
// ═══════════════════════════════════════════════

export function getDailyReportConfig(): DailyReportConfig {
  const raw = getSystemConfig('daily_report_config') || '{}';
  let parsed: Partial<DailyReportConfig> = {};
  try { parsed = JSON.parse(raw); } catch {}
  return {
    enabled: parsed.enabled !== false,
    time: parsed.time || '08:00',
    includeSearch: parsed.includeSearch !== false,
    includeSaves: parsed.includeSaves !== false,
    includeStorage: parsed.includeStorage !== false,
    includeUsers: parsed.includeUsers !== false,
    channels: parsed.channels || [],
  };
}

export function saveDailyReportConfig(cfg: Partial<DailyReportConfig>): void {
  const current = getDailyReportConfig();
  const merged = { ...current, ...cfg };
  const { getDb } = require('../database/database');
  const db = getDb();
  const existing = db.prepare("SELECT key FROM system_configs WHERE key = 'daily_report_config'").get();
  if (existing) {
    db.prepare("UPDATE system_configs SET value = ?, updated_at = datetime('now','localtime') WHERE key = 'daily_report_config'")
      .run(JSON.stringify(merged));
  } else {
    db.prepare("INSERT INTO system_configs (key, value, description) VALUES (?, ?, ?)")
      .run('daily_report_config', JSON.stringify(merged), 'Daily report configuration');
  }
}

// ═══════════════════════════════════════════════
// Report Generation
// ═══════════════════════════════════════════════

function getYesterday(): string {
  const d = new Date();
  d.setDate(d.getDate() - 1);
  return d.toISOString().slice(0, 10); // "2026-05-16"
}

function getYesterdayRange(): { start: string; end: string } {
  const date = getYesterday();
  return {
    start: `${date}T00:00:00`,
    end: `${date}T23:59:59`,
  };
}

export function generateDailyReport(dateOverride?: string): DailyReport {
  const db = getDb();
  const { start, end } = dateOverride
    ? { start: `${dateOverride}T00:00:00`, end: `${dateOverride}T23:59:59` }
    : getYesterdayRange();
  const date = dateOverride || getYesterday();

  // ── Searches ──
  let searchCount = 0;
  let uniqueSearchers = 0;
  try {
    const searchRow = db.prepare(
      "SELECT COUNT(*) as cnt FROM search_stats WHERE created_at >= ? AND created_at <= ?"
    ).get(start, end) as any;
    searchCount = searchRow?.cnt || 0;

    const searcherRow = db.prepare(
      "SELECT COUNT(DISTINCT ip_address) as cnt FROM search_stats WHERE created_at >= ? AND created_at <= ?"
    ).get(start, end) as any;
    uniqueSearchers = searcherRow?.cnt || 0;
  } catch {}

  // ── Saves ──
  let totalSaves = 0;
  let successSaves = 0;
  let failSaves = 0;
  let uniqueSavers = 0;
  try {
    const saveRow = db.prepare(
      "SELECT COUNT(*) as cnt FROM save_records WHERE created_at >= ? AND created_at <= ?"
    ).get(start, end) as any;
    totalSaves = saveRow?.cnt || 0;

    const successRow = db.prepare(
      "SELECT COUNT(*) as cnt FROM save_records WHERE created_at >= ? AND created_at <= ? AND status = 'success'"
    ).get(start, end) as any;
    successSaves = successRow?.cnt || 0;

    const failRow = db.prepare(
      "SELECT COUNT(*) as cnt FROM save_records WHERE created_at >= ? AND created_at <= ? AND status != 'success'"
    ).get(start, end) as any;
    failSaves = failRow?.cnt || 0;

    const saverRow = db.prepare(
      "SELECT COUNT(DISTINCT ip_address) as cnt FROM save_records WHERE created_at >= ? AND created_at <= ?"
    ).get(start, end) as any;
    uniqueSavers = saverRow?.cnt || 0;
  } catch {}

  // ── Per Cloud Breakdown ──
  const byCloud: DailyReport['byCloud'] = [];
  try {
    const clouds = getCloudConfigs();
    for (const c of clouds) {
      const cloudSaveRow = db.prepare(
        "SELECT COUNT(*) as cnt FROM save_records WHERE created_at >= ? AND created_at <= ? AND target_cloud = ?"
      ).get(start, end, c.cloud_type) as any;
      const cloudSuccessRow = db.prepare(
        "SELECT COUNT(*) as cnt FROM save_records WHERE created_at >= ? AND created_at <= ? AND target_cloud = ? AND status = 'success'"
      ).get(start, end, c.cloud_type) as any;

      byCloud.push({
        cloudType: c.cloud_type,
        nickname: c.nickname || '未知',
        saves: cloudSaveRow?.cnt || 0,
        successes: cloudSuccessRow?.cnt || 0,
        storageUsed: c.storage_used || 'N/A',
        storageTotal: c.storage_total || 'N/A',
        isActive: !!c.is_active,
      });
    }
  } catch {}

  return {
    date,
    searchCount,
    uniqueSearchers,
    saveCounts: { total: totalSaves, success: successSaves, fail: failSaves },
    byCloud,
    uniqueSavers,
  };
}

// ═══════════════════════════════════════════════
// Formatting
// ═══════════════════════════════════════════════

function formatStorage(used: string, total: string): string {
  try {
    const parseSize = (s: string): number => {
      const m = s.match(/^([\d.]+)\s*(B|KB|MB|GB|TB)$/i);
      if (!m) return 0;
      const units: Record<string, number> = { B: 1, KB: 1024, MB: 1024**2, GB: 1024**3, TB: 1024**4 };
      return parseFloat(m[1]) * (units[m[2].toUpperCase()] || 1);
    };
    const u = parseSize(used);
    const t = parseSize(total);
    if (t === 0) return `${used} / ${total}`;
    const pct = ((u / t) * 100).toFixed(1);
    return `${used} / ${total} (${pct}%)`;
  } catch {
    return `${used} / ${total}`;
  }
}



function cloudLabel(type: string): string {
  const short: Record<string, string> = { quark: "夸克", baidu: "百度", aliyun: "阿里云盘", "115": "115网盘", tianyi: "天翼云", "123pan": "123云盘", uc: "UC网盘", xunlei: "迅雷云盘", pikpak: "PikPak", magnet: "磁力链接", ed2k: "电驴链接", others: "其他" };
  return short[type] || (CLOUD_LABELS as Record<string,string>)[type] || type;
}

export function formatDailyReport(report: DailyReport, includeSearch = true, includeSaves = true, includeStorage = true, includeUsers = true): string {
  const lines: string[] = [];
  const formattedDate = report.date.replace(/-/g, '/');

  lines.push(`📊 **CloudSearch 每日汇报**`);
  lines.push(`📅 ${formattedDate}`);
  lines.push('');

  if (includeSearch && report.searchCount > 0) {
    lines.push(`🔍 **搜索统计**`);
    lines.push(`  总搜索: ${report.searchCount} 次`);
    if (includeUsers) lines.push(`  搜索用户: ${report.uniqueSearchers} 人`);
    lines.push('');
  }

  if (includeSaves) {
    const { total, success, fail } = report.saveCounts;
    lines.push(`💾 **转存统计**`);
    lines.push(`  总转存: ${total} 次`);
    lines.push(`  成功: ${success} 次  |  失败: ${fail} 次`);
    if (total > 0) lines.push(`  成功率: ${((success / total) * 100).toFixed(1)}%`);
    if (includeUsers) lines.push(`  转存用户: ${report.uniqueSavers} 人`);
    lines.push('');
  }

  if (includeStorage && report.byCloud.length > 0) {
    lines.push(`☁️ **网盘状态**`);
    for (const c of report.byCloud) {
      const icon = c.isActive ? '🟢' : '🔴';
      const label = cloudLabel(c.cloudType);
      if (c.saves > 0) {
        lines.push(`  ${icon} ${label} · ${c.nickname} · 转存 ${c.saves} 次 · ${formatStorage(c.storageUsed, c.storageTotal)}`);
      } else {
        lines.push(`  ${icon} ${label} · ${c.nickname} · ${formatStorage(c.storageUsed, c.storageTotal)}`);
      }
    }
    lines.push('');
  }

  if (report.saveCounts.total === 0 && report.searchCount === 0) {
    lines.push(`💤 昨日无活动记录`);
  }

  return lines.join('\n');
}

// ═══════════════════════════════════════════════
// Scheduler
// ═══════════════════════════════════════════════

let lastRunDate = '';

function getTodayStr(): string {
  return new Date().toISOString().slice(0, 10);
}

export async function runDailyReportIfScheduled(): Promise<void> {
  const cfg = getDailyReportConfig();
  if (!cfg.enabled) return;

  const now = new Date();
  const [hh, mm] = cfg.time.split(':').map(Number);
  const scheduledMinute = hh * 60 + mm;
  const currentMinute = now.getHours() * 60 + now.getMinutes();

  // Run within a 5-minute window of scheduled time
  const diff = currentMinute - scheduledMinute;
  if (diff < 0 || diff >= 5) return;

  const today = getTodayStr();
  if (lastRunDate === today) return; // already ran today

  lastRunDate = today;

  console.log(`[DailyReport] Running daily report for ${today}...`);
  try {
    const report = generateDailyReport();
    const content = formatDailyReport(
      report,
      cfg.includeSearch,
      cfg.includeSaves,
      cfg.includeStorage,
      cfg.includeUsers
    );

    // 通道过滤：如果配置了 channels 则只发指定通道
    if (cfg.channels && cfg.channels.length > 0) {
      const allChannels = getGlobalNotifyConfigs();
      const filtered = allChannels.filter(c => cfg.channels!.includes(c.name));
      if (filtered.length > 0) {
        sendToChannels(filtered, 'CloudSearch 每日汇报', content, 'info').catch(() => {});
      }
    } else {
      notify('CloudSearch 每日汇报', content, 'info');
    }

    // Record last run
    const { getDb } = require('../database/database');
    const db = getDb();
    const existing = db.prepare("SELECT key FROM system_configs WHERE key = 'daily_report_last_run'").get();
    if (existing) {
      db.prepare("UPDATE system_configs SET value = ?, updated_at = datetime('now','localtime') WHERE key = 'daily_report_last_run'")
        .run(JSON.stringify({ date: today, sentAt: new Date().toISOString() }));
    } else {
      db.prepare("INSERT INTO system_configs (key, value, description) VALUES (?, ?, ?)")
        .run('daily_report_last_run', JSON.stringify({ date: today, sentAt: new Date().toISOString() }), 'Last daily report run');
    }

    console.log(`[DailyReport] Report sent successfully for ${today}`);
  } catch (err: any) {
    console.error(`[DailyReport] Failed:`, err.message);
  }
}

// ═══════════════════════════════════════════════
// Manual test preview
// ═══════════════════════════════════════════════

export function previewDailyReport(dateOverride?: string): string {
  const report = generateDailyReport(dateOverride);
  const cfg = getDailyReportConfig();
  return formatDailyReport(
    report,
    cfg.includeSearch,
    cfg.includeSaves,
    cfg.includeStorage,
    cfg.includeUsers
  );
}

export async function sendTestDailyReport(): Promise<{ success: boolean; report: DailyReport }> {
  const report = generateDailyReport();
  const cfg = getDailyReportConfig();
  const content = formatDailyReport(
    report,
    cfg.includeSearch,
    cfg.includeSaves,
    cfg.includeStorage,
    cfg.includeUsers
  );
  const tcfg = getDailyReportConfig();
  if (tcfg.channels && tcfg.channels.length > 0) {
    const allChannels = getGlobalNotifyConfigs();
    const filtered = allChannels.filter(c => tcfg.channels!.includes(c.name));
    if (filtered.length > 0) {
      sendToChannels(filtered, 'CloudSearch 每日汇报 [测试]', content, 'info').catch(() => {});
    }
  } else {
    notify('CloudSearch 每日汇报 [测试]', content, 'info');
  }
  return { success: true, report };
}
