import 'server-only';
import { promises as fs } from 'fs';
import path from 'path';
import { dataMode } from './env';
import { execute, query } from './mysql';
import { supabaseAdmin, supabaseServer } from './supabase';
import type { Category, Database, Message, Product, Settings } from './types';

/* =====================================================================
   Veri katmani.

   Ayni fonksiyonlar uc kaynaktan birine yonlendirilir (bkz. lib/env.ts):
   MySQL (cPanel hosting) · Supabase · yerel dosya (demo modu).
   Sayfalar ve admin islemleri hangi kaynagin kullanildigini bilmez.
   ===================================================================== */

/* ------------------- yerel dosya adaptoru (demo modu) ---------------- */

const DB_PATH = path.join(process.cwd(), 'data', 'db.json');

async function readFileDb(): Promise<Database> {
  const raw = await fs.readFile(DB_PATH, 'utf-8');
  return JSON.parse(raw) as Database;
}

async function writeFileDb(db: Database): Promise<void> {
  await fs.writeFile(DB_PATH, JSON.stringify(db, null, 2), 'utf-8');
}

function newId(prefix: string) {
  return `${prefix}-${Math.random().toString(36).slice(2, 10)}`;
}

/* ------------------------- MySQL satir donusumu ---------------------- */

type Row = Record<string, unknown>;

function toCategory(r: Row): Category {
  return {
    id: String(r.id),
    slug: String(r.slug),
    name: String(r.name),
    description: (r.description as string | null) ?? null,
    image_url: (r.image_url as string | null) ?? null,
    sort_order: Number(r.sort_order),
    is_active: Boolean(r.is_active),
  };
}

function toProduct(r: Row): Product {
  return {
    id: String(r.id),
    category_id: String(r.category_id),
    name: String(r.name),
    description: (r.description as string | null) ?? null,
    unit: (r.unit as string | null) ?? null,
    price: r.price === null || r.price === undefined ? null : Number(r.price),
    image_url: (r.image_url as string | null) ?? null,
    is_featured: Boolean(r.is_featured),
    is_active: Boolean(r.is_active),
    sort_order: Number(r.sort_order),
  };
}

function toMessage(r: Row): Message {
  const created = r.created_at instanceof Date ? r.created_at : new Date(String(r.created_at));
  return {
    id: String(r.id),
    name: String(r.name),
    phone: String(r.phone),
    email: (r.email as string | null) ?? null,
    subject: (r.subject as string | null) ?? null,
    body: String(r.body),
    is_read: Boolean(r.is_read),
    created_at: created.toISOString(),
  };
}

/* ================================ okuma ============================== */

export async function listCategories(includeInactive = false): Promise<Category[]> {
  switch (dataMode()) {
    case 'mysql': {
      const rows = await query<Row>(
        `select * from categories ${includeInactive ? '' : 'where is_active = 1'}
         order by sort_order asc, name asc`
      );
      return rows.map(toCategory);
    }
    case 'supabase': {
      const sb = await supabaseServer();
      let q = sb.from('categories').select('*').order('sort_order', { ascending: true });
      if (!includeInactive) q = q.eq('is_active', true);
      const { data, error } = await q;
      if (error) throw new Error(error.message);
      return (data ?? []) as Category[];
    }
    default: {
      const db = await readFileDb();
      return db.categories
        .filter((c) => includeInactive || c.is_active)
        .sort((a, b) => a.sort_order - b.sort_order);
    }
  }
}

export async function listProducts(includeInactive = false): Promise<Product[]> {
  switch (dataMode()) {
    case 'mysql': {
      const rows = await query<Row>(
        `select * from products ${includeInactive ? '' : 'where is_active = 1'}
         order by sort_order asc, name asc`
      );
      return rows.map(toProduct);
    }
    case 'supabase': {
      const sb = await supabaseServer();
      let q = sb.from('products').select('*').order('sort_order', { ascending: true });
      if (!includeInactive) q = q.eq('is_active', true);
      const { data, error } = await q;
      if (error) throw new Error(error.message);
      return (data ?? []) as Product[];
    }
    default: {
      const db = await readFileDb();
      return db.products
        .filter((p) => includeInactive || p.is_active)
        .sort((a, b) => a.sort_order - b.sort_order);
    }
  }
}

export async function getSettings(): Promise<Settings> {
  switch (dataMode()) {
    case 'mysql': {
      const rows = await query<Row>(`select * from settings where id = 'site' limit 1`);
      if (!rows[0]) throw new Error("settings tablosunda 'site' kaydi bulunamadi.");
      const r = rows[0];
      const out: Record<string, string> = { id: 'site' };
      for (const [k, v] of Object.entries(r)) {
        if (k === 'id' || k === 'updated_at') continue;
        out[k] = v === null || v === undefined ? '' : String(v);
      }
      return out as unknown as Settings;
    }
    case 'supabase': {
      const sb = await supabaseServer();
      const { data, error } = await sb.from('settings').select('*').eq('id', 'site').single();
      if (error) throw new Error(error.message);
      return data as Settings;
    }
    default: {
      const db = await readFileDb();
      return db.settings;
    }
  }
}

export async function listMessages(): Promise<Message[]> {
  switch (dataMode()) {
    case 'mysql': {
      const rows = await query<Row>(`select * from messages order by created_at desc limit 500`);
      return rows.map(toMessage);
    }
    case 'supabase': {
      const sb = supabaseAdmin();
      const { data, error } = await sb
        .from('messages')
        .select('*')
        .order('created_at', { ascending: false });
      if (error) throw new Error(error.message);
      return (data ?? []) as Message[];
    }
    default: {
      const db = await readFileDb();
      return [...(db.messages ?? [])].sort((a, b) => b.created_at.localeCompare(a.created_at));
    }
  }
}

/* ================================ yazma ============================== */

export async function saveCategory(input: Partial<Category>): Promise<void> {
  switch (dataMode()) {
    case 'mysql': {
      const slug = input.slug || slugify(input.name ?? '');
      if (input.id) {
        await execute(
          `update categories set slug=?, name=?, description=?, image_url=?, sort_order=?, is_active=?
           where id=?`,
          [
            slug,
            input.name,
            input.description ?? null,
            input.image_url ?? null,
            input.sort_order ?? 99,
            input.is_active ? 1 : 0,
            input.id,
          ]
        );
      } else {
        await execute(
          `insert into categories (slug, name, description, image_url, sort_order, is_active)
           values (?, ?, ?, ?, ?, ?)`,
          [
            slug,
            input.name,
            input.description ?? null,
            input.image_url ?? null,
            input.sort_order ?? 99,
            input.is_active === false ? 0 : 1,
          ]
        );
      }
      return;
    }
    case 'supabase': {
      const sb = supabaseAdmin();
      const row = {
        slug: input.slug,
        name: input.name,
        description: input.description ?? null,
        image_url: input.image_url ?? null,
        sort_order: input.sort_order ?? 99,
        is_active: input.is_active ?? true,
      };
      const { error } = input.id
        ? await sb.from('categories').update(row).eq('id', input.id)
        : await sb.from('categories').insert(row);
      if (error) throw new Error(error.message);
      return;
    }
    default: {
      const db = await readFileDb();
      const idx = db.categories.findIndex((c) => c.id === input.id);
      if (idx >= 0) {
        db.categories[idx] = { ...db.categories[idx], ...input } as Category;
      } else {
        const slug = input.slug || slugify(input.name ?? '') || newId('kategori');
        db.categories.push({
          id: slug,
          slug,
          name: input.name ?? 'Yeni kategori',
          description: input.description ?? null,
          image_url: input.image_url ?? null,
          sort_order: input.sort_order ?? db.categories.length + 1,
          is_active: input.is_active ?? true,
        });
      }
      await writeFileDb(db);
    }
  }
}

export async function deleteCategory(id: string): Promise<void> {
  switch (dataMode()) {
    case 'mysql':
      await execute(`delete from categories where id = ?`, [id]);
      return;
    case 'supabase': {
      const sb = supabaseAdmin();
      const { error } = await sb.from('categories').delete().eq('id', id);
      if (error) throw new Error(error.message);
      return;
    }
    default: {
      const db = await readFileDb();
      db.categories = db.categories.filter((c) => c.id !== id);
      db.products = db.products.filter((p) => p.category_id !== id);
      await writeFileDb(db);
    }
  }
}

export async function saveProduct(input: Partial<Product>): Promise<void> {
  switch (dataMode()) {
    case 'mysql': {
      const values = [
        input.category_id,
        input.name,
        input.description ?? null,
        input.unit ?? null,
        input.price ?? null,
        input.image_url ?? null,
        input.is_featured ? 1 : 0,
        input.is_active ? 1 : 0,
        input.sort_order ?? 99,
      ];
      if (input.id) {
        await execute(
          `update products set category_id=?, name=?, description=?, unit=?, price=?,
                  image_url=?, is_featured=?, is_active=?, sort_order=? where id=?`,
          [...values, input.id]
        );
      } else {
        await execute(
          `insert into products (category_id, name, description, unit, price,
                                 image_url, is_featured, is_active, sort_order)
           values (?, ?, ?, ?, ?, ?, ?, ?, ?)`,
          values
        );
      }
      return;
    }
    case 'supabase': {
      const sb = supabaseAdmin();
      const row = {
        category_id: input.category_id,
        name: input.name,
        description: input.description ?? null,
        unit: input.unit ?? null,
        price: input.price ?? null,
        image_url: input.image_url ?? null,
        is_featured: input.is_featured ?? false,
        is_active: input.is_active ?? true,
        sort_order: input.sort_order ?? 99,
      };
      const { error } = input.id
        ? await sb.from('products').update(row).eq('id', input.id)
        : await sb.from('products').insert(row);
      if (error) throw new Error(error.message);
      return;
    }
    default: {
      const db = await readFileDb();
      const idx = db.products.findIndex((p) => p.id === input.id);
      if (idx >= 0) {
        db.products[idx] = { ...db.products[idx], ...input } as Product;
      } else {
        db.products.push({
          id: newId('urun'),
          category_id: input.category_id ?? db.categories[0]?.id ?? '',
          name: input.name ?? 'Yeni ürün',
          description: input.description ?? null,
          unit: input.unit ?? null,
          price: input.price ?? null,
          image_url: input.image_url ?? null,
          is_featured: input.is_featured ?? false,
          is_active: input.is_active ?? true,
          sort_order: input.sort_order ?? db.products.length + 1,
        });
      }
      await writeFileDb(db);
    }
  }
}

export async function deleteProduct(id: string): Promise<void> {
  switch (dataMode()) {
    case 'mysql':
      await execute(`delete from products where id = ?`, [id]);
      return;
    case 'supabase': {
      const sb = supabaseAdmin();
      const { error } = await sb.from('products').delete().eq('id', id);
      if (error) throw new Error(error.message);
      return;
    }
    default: {
      const db = await readFileDb();
      db.products = db.products.filter((p) => p.id !== id);
      await writeFileDb(db);
    }
  }
}

/** settings tablosunda guncellenmesine izin verilen sutunlar. */
const SETTING_COLUMNS = [
  'brand_name',
  'tagline',
  'hero_title',
  'hero_subtitle',
  'about_title',
  'about_body',
  'phone',
  'whatsapp',
  'email',
  'address',
  'working_hours',
  'instagram',
  'facebook',
  'map_embed_url',
] as const;

export async function saveSettings(input: Partial<Settings>): Promise<void> {
  switch (dataMode()) {
    case 'mysql': {
      const cols = SETTING_COLUMNS.filter((c) => input[c] !== undefined);
      if (cols.length === 0) return;
      await execute(
        `update settings set ${cols.map((c) => `${c}=?`).join(', ')} where id = 'site'`,
        cols.map((c) => input[c] ?? '')
      );
      return;
    }
    case 'supabase': {
      const sb = supabaseAdmin();
      const { error } = await sb.from('settings').update(input).eq('id', 'site');
      if (error) throw new Error(error.message);
      return;
    }
    default: {
      const db = await readFileDb();
      db.settings = { ...db.settings, ...input, id: 'site' };
      await writeFileDb(db);
    }
  }
}

export async function createMessage(
  input: Omit<Message, 'id' | 'created_at' | 'is_read'>
): Promise<void> {
  switch (dataMode()) {
    case 'mysql':
      await execute(
        `insert into messages (name, phone, email, subject, body, is_read)
         values (?, ?, ?, ?, ?, 0)`,
        [input.name, input.phone, input.email ?? null, input.subject ?? null, input.body]
      );
      return;
    case 'supabase': {
      const sb = supabaseAdmin();
      const { error } = await sb.from('messages').insert({ ...input, is_read: false });
      if (error) throw new Error(error.message);
      return;
    }
    default: {
      const db = await readFileDb();
      db.messages = db.messages ?? [];
      db.messages.push({
        ...input,
        id: newId('mesaj'),
        is_read: false,
        created_at: new Date().toISOString(),
      });
      await writeFileDb(db);
    }
  }
}

export async function setMessageRead(id: string, is_read: boolean): Promise<void> {
  switch (dataMode()) {
    case 'mysql':
      await execute(`update messages set is_read = ? where id = ?`, [is_read ? 1 : 0, id]);
      return;
    case 'supabase': {
      const sb = supabaseAdmin();
      const { error } = await sb.from('messages').update({ is_read }).eq('id', id);
      if (error) throw new Error(error.message);
      return;
    }
    default: {
      const db = await readFileDb();
      const m = (db.messages ?? []).find((x) => x.id === id);
      if (m) m.is_read = is_read;
      await writeFileDb(db);
    }
  }
}

export async function deleteMessage(id: string): Promise<void> {
  switch (dataMode()) {
    case 'mysql':
      await execute(`delete from messages where id = ?`, [id]);
      return;
    case 'supabase': {
      const sb = supabaseAdmin();
      const { error } = await sb.from('messages').delete().eq('id', id);
      if (error) throw new Error(error.message);
      return;
    }
    default: {
      const db = await readFileDb();
      db.messages = (db.messages ?? []).filter((m) => m.id !== id);
      await writeFileDb(db);
    }
  }
}

/* ------------------------------- yardimci ---------------------------- */

const TR_MAP: Record<string, string> = {
  ç: 'c', Ç: 'c', ğ: 'g', Ğ: 'g', ı: 'i', İ: 'i',
  ö: 'o', Ö: 'o', ş: 's', Ş: 's', ü: 'u', Ü: 'u',
};

export function slugify(input: string): string {
  return input
    .replace(/[çÇğĞıİöÖşŞüÜ]/g, (c) => TR_MAP[c] ?? c)
    .toLowerCase()
    .replace(/[^a-z0-9]+/g, '-')
    .replace(/^-+|-+$/g, '');
}
