import * as SQLite from "expo-sqlite";

const db = SQLite.openDatabaseSync("toptran.db");

export type UsuarioDB = {
  id: string;
  email: string;
  name: string;
  token: string;
  created_at: string;
};

export type CorridaDB = {
  id: string;
  usuario_id: string;
  empresa: string;
  km: number;
  custo_por_km: number;
  total: number;
  data: string;
  sincronizado: 0 | 1;
  created_at: string;
};

export const initDB = async () => {
  try {
    await db.execAsync(
      `CREATE TABLE IF NOT EXISTS usuarios (
        id TEXT PRIMARY KEY,
        email TEXT UNIQUE NOT NULL,
        name TEXT NOT NULL,
        token TEXT NOT NULL,
        created_at TEXT DEFAULT CURRENT_TIMESTAMP
      );`,
    );
    await db.execAsync(
      `CREATE TABLE IF NOT EXISTS corridas (
        id TEXT PRIMARY KEY,
        usuario_id TEXT NOT NULL,
        empresa TEXT NOT NULL,
        km REAL NOT NULL,
        custo_por_km REAL NOT NULL,
        total REAL NOT NULL,
        data TEXT NOT NULL,
        sincronizado INTEGER DEFAULT 0,
        created_at TEXT DEFAULT CURRENT_TIMESTAMP,
        FOREIGN KEY (usuario_id) REFERENCES usuarios(id)
      );`,
    );
    await db.execAsync(
      `CREATE TABLE IF NOT EXISTS settings (
        key TEXT PRIMARY KEY,
        value TEXT NOT NULL
      );`,
    );
    await db.execAsync(
      `CREATE TABLE IF NOT EXISTS empresas (
        id TEXT PRIMARY KEY,
        nome TEXT NOT NULL,
        custo_por_km REAL NOT NULL,
        observacoes TEXT DEFAULT '',
        created_at TEXT DEFAULT CURRENT_TIMESTAMP
      );`,
    );
  } catch (error) {
    console.error("Failed to initialize database:", error);
    throw error;
  }
};

// SETTINGS (key-value store)
export const getSetting = async (key: string): Promise<string | null> => {
  try {
    const row = await db.getFirstAsync<{ value: string }>(
      `SELECT value FROM settings WHERE key = ?`,
      [key],
    );
    return row?.value ?? null;
  } catch (error) {
    console.error("Error reading setting:", error);
    throw error;
  }
};

export const setSetting = async (key: string, value: string): Promise<void> => {
  try {
    await db.runAsync(
      `INSERT OR REPLACE INTO settings (key, value) VALUES (?, ?)`,
      [key, value],
    );
  } catch (error) {
    console.error("Error writing setting:", error);
    throw error;
  }
};

export const deleteSetting = async (key: string): Promise<void> => {
  try {
    await db.runAsync(`DELETE FROM settings WHERE key = ?`, [key]);
  } catch (error) {
    console.error("Error deleting setting:", error);
    throw error;
  }
};

// USUÁRIOS
export const salvarUsuario = async (
  usuario: Omit<UsuarioDB, "created_at">,
): Promise<string> => {
  try {
    const existing = await db.getFirstAsync<{ id: string }>(
      `SELECT id FROM usuarios WHERE email = ?`,
      [usuario.email],
    );

    if (existing) {
      // Preserva o ID original — apenas atualiza nome e token
      await db.runAsync(
        `UPDATE usuarios SET name = ?, token = ? WHERE email = ?`,
        [usuario.name, usuario.token, usuario.email],
      );
      return existing.id;
    }

    await db.runAsync(
      `INSERT INTO usuarios (id, email, name, token) VALUES (?, ?, ?, ?)`,
      [usuario.id, usuario.email, usuario.name, usuario.token],
    );
    return usuario.id;
  } catch (error) {
    console.error("Error saving user:", error);
    throw error;
  }
};

export const obterUsuario = async (
  usuarioId: string,
): Promise<UsuarioDB | null> => {
  try {
    const result = await db.getFirstAsync<UsuarioDB>(
      `SELECT * FROM usuarios WHERE id = ?`,
      [usuarioId],
    );
    return result || null;
  } catch (error) {
    console.error("Error fetching user:", error);
    throw error;
  }
};

// CORRIDAS
export const salvarCorrida = async (corrida: Omit<CorridaDB, "created_at">) => {
  try {
    const result = await db.runAsync(
      `INSERT INTO corridas (id, usuario_id, empresa, km, custo_por_km, total, data, sincronizado)
       VALUES (?, ?, ?, ?, ?, ?, ?, ?)`,
      [
        corrida.id,
        corrida.usuario_id,
        corrida.empresa,
        corrida.km,
        corrida.custo_por_km,
        corrida.total,
        corrida.data,
        corrida.sincronizado,
      ],
    );
    return result;
  } catch (error) {
    console.error("Error saving corrida:", error);
    throw error;
  }
};

export const obterCorridas = async (
  usuarioId: string,
): Promise<CorridaDB[]> => {
  try {
    const result = await db.getAllAsync<CorridaDB>(
      `SELECT * FROM corridas WHERE usuario_id = ? ORDER BY created_at DESC`,
      [usuarioId],
    );
    return result || [];
  } catch (error) {
    console.error("Error fetching corridas:", error);
    throw error;
  }
};

export const obterCorridasNaoSincronizadas = async (
  usuarioId: string,
): Promise<CorridaDB[]> => {
  try {
    const result = await db.getAllAsync<CorridaDB>(
      `SELECT * FROM corridas WHERE usuario_id = ? AND sincronizado = 0`,
      [usuarioId],
    );
    return result || [];
  } catch (error) {
    console.error("Error fetching unsync corridas:", error);
    throw error;
  }
};

export const marcarCorridaComoSincronizada = async (corridaId: string) => {
  try {
    await db.runAsync(`UPDATE corridas SET sincronizado = 1 WHERE id = ?`, [
      corridaId,
    ]);
  } catch (error) {
    console.error("Error marking corrida as synced:", error);
    throw error;
  }
};

export const deletarCorrida = async (corridaId: string) => {
  try {
    await db.runAsync(`DELETE FROM corridas WHERE id = ?`, [corridaId]);
  } catch (error) {
    console.error("Error deleting corrida:", error);
    throw error;
  }
};

export const limparBancoDados = async () => {
  try {
    await db.execAsync(`DELETE FROM corridas; DELETE FROM usuarios;`);
    console.log("Database cleared");
  } catch (error) {
    console.error("Error clearing database:", error);
    throw error;
  }
};

// EMPRESAS
export type EmpresaDB = {
  id: string;
  nome: string;
  custo_por_km: number;
  observacoes: string;
  created_at: string;
};

export const obterEmpresas = async (): Promise<EmpresaDB[]> => {
  try {
    return (
      (await db.getAllAsync<EmpresaDB>(
        `SELECT * FROM empresas ORDER BY nome ASC`,
      )) ?? []
    );
  } catch (error) {
    console.error("Error fetching empresas:", error);
    throw error;
  }
};

export const salvarEmpresa = async (
  empresa: Omit<EmpresaDB, "created_at">,
): Promise<void> => {
  try {
    await db.runAsync(
      `INSERT INTO empresas (id, nome, custo_por_km, observacoes) VALUES (?, ?, ?, ?)`,
      [empresa.id, empresa.nome, empresa.custo_por_km, empresa.observacoes],
    );
  } catch (error) {
    console.error("Error saving empresa:", error);
    throw error;
  }
};

export const atualizarEmpresa = async (
  empresa: Omit<EmpresaDB, "created_at">,
): Promise<void> => {
  try {
    await db.runAsync(
      `UPDATE empresas SET nome = ?, custo_por_km = ?, observacoes = ? WHERE id = ?`,
      [empresa.nome, empresa.custo_por_km, empresa.observacoes, empresa.id],
    );
  } catch (error) {
    console.error("Error updating empresa:", error);
    throw error;
  }
};

export const deletarEmpresa = async (id: string): Promise<void> => {
  try {
    await db.runAsync(`DELETE FROM empresas WHERE id = ?`, [id]);
  } catch (error) {
    console.error("Error deleting empresa:", error);
    throw error;
  }
};
