// Use legacy API for documentDirectory compatibility
import * as FileSystem from 'expo-file-system/legacy';
import * as Sharing from 'expo-sharing';
import type { MeasurementFrame } from '../protocol/types';
import { formatUtc, formatCoord } from './format';

const DATA_DIR = (FileSystem.documentDirectory ?? '') + 'tem_data/';

async function ensureDir() {
  const info = await FileSystem.getInfoAsync(DATA_DIR);
  if (!info.exists) await FileSystem.makeDirectoryAsync(DATA_DIR, { intermediates: true });
}

// Build CSV content for a list of frames
function framesToCsv(frames: MeasurementFrame[]): string {
  if (frames.length === 0) return '';

  const channelNum = frames[0].meta.channelNum;
  const chHeaders = Array.from({ length: channelNum }, (_, i) => `CH${i + 1}_peak_uV`).join(',');
  const header = `FrameID,UTC,Longitude,Latitude,Altitude,GPS,SD,AmpRatio,Current,Temp,Battery,Roll,Pitch,Yaw,${chHeaders}`;

  const rows = frames.map((f) => {
    const m = f.meta;
    const peaks = f.adcUV.map((ch) => {
      const maxAbs = ch.reduce((mx, v) => Math.max(mx, Math.abs(v)), 0);
      return maxAbs.toFixed(4);
    });
    return [
      f.frameId,
      formatUtc(m.utc),
      m.longitude.toFixed(7),
      m.latitude.toFixed(7),
      m.altitude.toFixed(2),
      m.gpsStatus,
      m.sdStatus,
      m.ampRatio,
      m.current,
      m.temperature,
      m.batteryVolt,
      m.roll.toFixed(2),
      m.pitch.toFixed(2),
      m.yaw.toFixed(2),
      ...peaks,
    ].join(',');
  });

  return [header, ...rows].join('\n');
}

export async function exportCsv(frames: MeasurementFrame[], sessionId: string): Promise<string> {
  await ensureDir();
  const filename = `TEM_${sessionId}.csv`;
  const path = DATA_DIR + filename;
  const csv = framesToCsv(frames);
  await FileSystem.writeAsStringAsync(path, csv, { encoding: FileSystem.EncodingType.UTF8 });
  return path;
}

// Save a single frame's raw ADC data as binary file
export async function saveFrameBin(frame: MeasurementFrame, sessionId: string): Promise<string> {
  await ensureDir();
  const filename = `${sessionId}_f${String(frame.frameId).padStart(6, '0')}.bin`;
  const path = DATA_DIR + filename;

  const channelNum = frame.adcRaw.length;
  const samplesPerCh = frame.adcRaw[0]?.length ?? 0;
  // Header: magic(4) + channelNum(4) + samplesPerCh(4) = 12 bytes
  const totalBytes = 12 + channelNum * samplesPerCh * 4;
  const buf = new ArrayBuffer(totalBytes);
  const view = new DataView(buf);

  // Magic: "TEM\x01"
  view.setUint8(0, 0x54); view.setUint8(1, 0x45); view.setUint8(2, 0x4d); view.setUint8(3, 0x01);
  view.setUint32(4, channelNum, true);
  view.setUint32(8, samplesPerCh, true);

  let offset = 12;
  for (const ch of frame.adcRaw) {
    for (let i = 0; i < ch.length; i++) {
      view.setInt32(offset, ch[i], true);
      offset += 4;
    }
  }

  // Convert ArrayBuffer to base64 string for expo-file-system
  const uint8 = new Uint8Array(buf);
  let binary = '';
  for (let i = 0; i < uint8.length; i++) binary += String.fromCharCode(uint8[i]);
  const b64 = btoa(binary);
  await FileSystem.writeAsStringAsync(path, b64, { encoding: FileSystem.EncodingType.Base64 });
  return path;
}

function getMime(filePath: string): string {
  const ext = filePath.split('.').pop()?.toLowerCase();
  const map: Record<string, string> = {
    csv: 'text/csv', tem: 'application/octet-stream',
    bin: 'application/octet-stream', json: 'application/json',
  };
  return map[ext ?? ''] ?? 'application/octet-stream';
}

function getFileName(filePath: string): string {
  return filePath.split('/').pop() ?? 'export';
}

async function saveToFile(filePath: string): Promise<boolean> {
  try {
    const perms = await FileSystem.StorageAccessFramework.requestDirectoryPermissionsAsync();
    if (!perms.granted) return false;

    const fileName = getFileName(filePath);
    const mime = getMime(filePath);
    const destUri = await FileSystem.StorageAccessFramework.createFileAsync(
      perms.directoryUri, fileName, mime,
    );

    const content = await FileSystem.readAsStringAsync(filePath, {
      encoding: FileSystem.EncodingType.Base64,
    });
    await FileSystem.writeAsStringAsync(destUri, content, {
      encoding: FileSystem.EncodingType.Base64,
    });
    return true;
  } catch {
    return false;
  }
}

export async function shareFile(filePath: string) {
  const { Alert } = require('react-native');
  const canShare = await Sharing.isAvailableAsync();

  Alert.alert('导出方式', getFileName(filePath), [
    canShare ? {
      text: '分享',
      onPress: () => Sharing.shareAsync(filePath, {
        mimeType: getMime(filePath),
        dialogTitle: '导出数据',
      }),
    } : null,
    {
      text: '保存到文件',
      onPress: async () => {
        const ok = await saveToFile(filePath);
        if (ok) Alert.alert('保存成功', '文件已保存到所选目录');
        else Alert.alert('保存取消', '未选择保存位置或保存失败');
      },
    },
    { text: '取消', style: 'cancel' },
  ].filter(Boolean));
}

export async function listSessionFiles(sessionId: string): Promise<string[]> {
  await ensureDir();
  const all = await FileSystem.readDirectoryAsync(DATA_DIR);
  return all.filter((f) => f.startsWith(sessionId)).map((f) => DATA_DIR + f);
}
