// store.js — Supabase + DEMO localStorage fallback 추상화
// 모든 데이터 접근은 이 스토어 하나로

export function createStore(cfg) {
  const isDemo = cfg.DEMO_MODE || !cfg.SUPABASE_URL.includes('supabase.co') || cfg.SUPABASE_URL.startsWith('https://YOUR-');

  if (isDemo) return createDemoStore();
  return createSupabaseStore(cfg);
}

// ============================================================
// DEMO 모드 — localStorage + 더미 시드
// ============================================================
function createDemoStore() {
  const KEY_PREFIX = 'tktx_';
  const seed = {
    cms: {
      hero: {
        title: '이선생 TKTX', tagline: '통관 고유번호 한 번에', subtitle: '정품 타투 마취 크림 · 직구',
        stamp1: '정품 인증', stamp2: '직구 전용', stamp3: 'SINCE 2026'
      },
      mente: { body: '이선생 TKTX는 정품 마취 크림만 직구로 제공합니다.\n중간 마진 없는 합리적 가격, 그리고 통관까지 한 번에.\n타투이스트와 고객 모두를 위한 가장 깔끔한 루트.' },
      footer: {
        brand_line: '이선생 TKTX',
        line1: '정품만 직구로 · 통관 고유번호 필수',
        line2: '© 2026 LEESEONSAENG TKTX'
      },
      main_channel: {
        enabled: true,
        icon: 'telegram',
        label: 'Telegram 메인 채널',
        sublabel: '실시간 응대 · 공지 + 신규 입고',
        url: 'https://t.me/+a45_Ib2BOYMwOTZl'
      },
      floating: {
        // 2026-04-28: 새 순서 — 텔레그램 → 라인 → 인스타그램 → 카카오톡 (사용자 요청)
        order: ['telegram', 'line', 'instagram', 'kakao'],
        telegram:  { enabled: true,  url: 'https://t.me/+a45_Ib2BOYMwOTZl' },
        kakao:     { enabled: false, url: 'https://www.kakaocorp.com' },
        line:      { enabled: false, url: 'https://line.me' },
        instagram: { enabled: true,  url: 'https://www.instagram.com' }
      },
      inquiry_kakao: { enabled: true, url: 'https://pf.kakao.com/_xexample', label: '카톡 채널로 빠른 문의' },
      // 2026-04-29: 문의 섹션 인트로 멘트 CMS化 (사용자 요청)
      inquiry: { intro: '편하신 채널로 연락 주세요. 빠르게 답변드리겠습니다.' },
      urgent_notice: { enabled: false, title: '신규 입고 안내', body: 'TKTX 60% 9개 박스 신규 입고되었습니다.\n주문 폭주로 일부 지연 가능성 있으니 양해 부탁드립니다.', cta_label: '제품 보러가기', cta_url: '#products' }
    },
    notices: [
      { id: 1, title: '통관 고유번호 안내', body: '직구 시 통관 고유번호가 반드시 필요합니다. 발급은 무료이며 약 1~2분 소요됩니다.\n아래 링크에서 바로 발급받으세요.', external_url: 'https://unipass.customs.go.kr/csp/persIndex.do', pinned: true, created_at: '2026-04-20T00:00:00Z' },
      { id: 2, title: '신규 입고 — TKTX 60% 9개 박스', body: '베스트셀러 60% 농도 9개 박스 신규 입고. 한정 수량입니다.', external_url: '', pinned: false, created_at: '2026-04-25T00:00:00Z' },
      { id: 3, title: '배송 안내', body: '통관 후 영업일 기준 2~3일 내 배송됩니다. 평일 14시 이전 주문 당일 출고.', external_url: '', pinned: false, created_at: '2026-04-26T00:00:00Z' },
      { id: 4, title: '진품 인증 방법', body: 'TKTX 정품은 박스 측면 홀로그램과 시리얼 넘버로 확인 가능합니다.', external_url: '', pinned: false, created_at: '2026-04-27T00:00:00Z' }
    ],
    products: [
      { id: 1, name: 'TKTX 40%', price: 35000, image_url: '', description: '입문 농도 · 안정적 마취감', sort_order: 1 },
      { id: 2, name: 'TKTX 60%', price: 50000, image_url: '', description: '베스트셀러 · 강한 마취감', sort_order: 2 },
      { id: 3, name: 'TKTX 9개 박스', price: 380000, image_url: '', description: '대용량 박스 · 단가 절감', sort_order: 3 },
      { id: 4, name: '만통롤라', price: 55000, image_url: '', description: '롤라 타입 · 광범위 도포', sort_order: 4 }
    ],
    qna: [
      { id: 1, question: '통관 고유번호는 어디서 받나요?', answer: '관세청 UNIPASS에서 무료로 1~2분 내 발급됩니다.\n발급 후 주문 시 입력해 주세요.', external_url: 'https://unipass.customs.go.kr/csp/persIndex.do', external_label: '통관 고유번호 받으러 가기', sort_order: 1 },
      { id: 2, question: '농도는 어떻게 선택하나요?', answer: '입문/얇은 라인은 40%, 컬러/면적이 큰 작업은 60%를 추천합니다.', external_url: '', external_label: '', sort_order: 2 },
      { id: 3, question: '배송 기간은 얼마나 걸리나요?', answer: '통관 후 영업일 기준 2~3일. 평일 14시 이전 주문은 당일 출고됩니다.', external_url: '', external_label: '', sort_order: 3 },
      { id: 4, question: '정품 확인 방법은?', answer: '박스 측면 홀로그램 스티커와 시리얼 넘버 두 가지로 확인 가능합니다.', external_url: '', external_label: '', sort_order: 4 }
    ],
    reviews: [
      { id: 1, author: 'TT***', body: '60% 정말 만족합니다. 작업 내내 편했어요. 재구매 갑니다.', rating: 5, is_private: false, password_hash: '', created_at: '2026-04-22T00:00:00Z' },
      { id: 2, author: 'IN***', body: '40%로 시작했는데 입문용으로 딱이에요. 통관도 빨랐습니다.', rating: 5, is_private: false, password_hash: '', created_at: '2026-04-23T00:00:00Z' },
      { id: 3, author: 'SH***', body: '9개 박스 단가가 정말 좋네요. 샵 운영하시는 분께 추천.', rating: 5, is_private: false, password_hash: '', created_at: '2026-04-24T00:00:00Z' },
      { id: 4, author: '익명', body: '비공개 후기입니다.', rating: 5, is_private: true, password_hash: '', created_at: '2026-04-25T00:00:00Z' },
      { id: 5, author: 'JK***', body: '만통롤라 처음 써봤는데 광범위에 좋네요.', rating: 4, is_private: false, password_hash: '', created_at: '2026-04-26T00:00:00Z' },
      { id: 6, author: 'PM***', body: '문의에 답변이 빨라서 좋았습니다.', rating: 5, is_private: false, password_hash: '', created_at: '2026-04-27T00:00:00Z' }
    ],
    external_links: [
      { id: 1, label: '통관 고유번호 발급', url: 'https://unipass.customs.go.kr/csp/persIndex.do', position: 'top', sort_order: 1, enabled: true },
      { id: 2, label: '인스타그램', url: 'https://www.instagram.com', position: 'middle', sort_order: 1, enabled: true },
      { id: 3, label: '제품 카탈로그 PDF', url: '#', position: 'bottom', sort_order: 1, enabled: true }
    ]
  };

  // 시드 주입 (한번만 — 전체)
  if (!localStorage.getItem(KEY_PREFIX + 'seeded')) {
    Object.entries(seed).forEach(([k, v]) => {
      localStorage.setItem(KEY_PREFIX + k, JSON.stringify(v));
    });
    localStorage.setItem(KEY_PREFIX + 'seeded', '1');
  }

  // 신규 추가 키 보강 (매 부팅 — 기존 사장님 입력값 손실 0)
  // 새로 추가된 cms 키(footer, main_channel, hero.stampN 등)가 누락된 사용자에게만 시드 주입
  try {
    const existingCms = JSON.parse(localStorage.getItem(KEY_PREFIX + 'cms') || '{}');
    let changed = false;
    for (const [k, v] of Object.entries(seed.cms)) {
      if (existingCms[k] === undefined) {
        existingCms[k] = v; changed = true;
      } else if (k === 'hero' && typeof existingCms[k] === 'object') {
        for (const subKey of ['stamp1','stamp2','stamp3']) {
          if (existingCms[k][subKey] === undefined) { existingCms[k][subKey] = v[subKey]; changed = true; }
        }
      } else if (k === 'main_channel' && typeof existingCms[k] === 'object') {
        // 2026-04-28: main_channel.url 비어 있으면 시드 url 강제 주입 (사용자 hidden 이슈 방지)
        if (!existingCms[k].url) { existingCms[k].url = v.url; changed = true; }
        if (existingCms[k].enabled === undefined) { existingCms[k].enabled = v.enabled; changed = true; }
        if (!existingCms[k].label) { existingCms[k].label = v.label; changed = true; }
        if (!existingCms[k].sublabel) { existingCms[k].sublabel = v.sublabel; changed = true; }
        if (!existingCms[k].icon) { existingCms[k].icon = v.icon; changed = true; }
      } else if (k === 'footer' && typeof existingCms[k] === 'object') {
        for (const subKey of ['brand_line','line1','line2']) {
          if (!existingCms[k][subKey]) { existingCms[k][subKey] = v[subKey]; changed = true; }
        }
      } else if (k === 'floating' && typeof existingCms[k] === 'object') {
        // 2026-04-28: order 필드 누락 보강 (사장님 입력 channel 데이터는 보존)
        if (!Array.isArray(existingCms[k].order)) {
          existingCms[k].order = v.order;
          changed = true;
        }
      } else if (k === 'inquiry' && typeof existingCms[k] === 'object') {
        if (!existingCms[k].intro) { existingCms[k].intro = v.intro; changed = true; }
      }
    }
    if (changed) localStorage.setItem(KEY_PREFIX + 'cms', JSON.stringify(existingCms));
  } catch { /* 보강 실패는 무시 — 기본 시드로 계속 작동 */ }

  function read(key) {
    const raw = localStorage.getItem(KEY_PREFIX + key);
    return raw ? JSON.parse(raw) : null;
  }
  function write(key, val) {
    try {
      localStorage.setItem(KEY_PREFIX + key, JSON.stringify(val));
    } catch (e) {
      if (e && (e.name === 'QuotaExceededError' || /quota/i.test(e.message || ''))) {
        throw new Error('저장 공간이 가득 찼습니다. 사진 매수를 줄이거나 더 작은 사진으로 다시 시도해 주세요.');
      }
      throw e;
    }
  }

  return {
    isDemo: true,

    async getCmsConfig() {
      return read('cms') || {};
    },
    async setCmsConfig(key, value) {
      const cms = read('cms') || {};
      cms[key] = value;
      write('cms', cms);
    },

    async list(table) {
      const arr = read(table) || [];
      if (table === 'notices') return arr.sort((a,b) => (b.pinned - a.pinned) || (new Date(b.created_at) - new Date(a.created_at)));
      if (table === 'products' || table === 'qna') return arr.sort((a,b) => a.sort_order - b.sort_order);
      if (table === 'reviews' || table === 'inquiries') return arr.sort((a,b) => new Date(b.created_at) - new Date(a.created_at));
      if (table === 'external_links') return arr.filter(x => x.enabled).sort((a,b) => a.sort_order - b.sort_order);
      return arr;
    },

    async insert(table, row) {
      const arr = read(table) || [];
      const id = arr.length ? Math.max(...arr.map(x => x.id)) + 1 : 1;
      const newRow = { id, created_at: new Date().toISOString(), ...row };
      arr.push(newRow);
      write(table, arr);
      return newRow;
    },

    async update(table, id, patch) {
      const arr = read(table) || [];
      const i = arr.findIndex(x => x.id === id);
      if (i < 0) return null;
      arr[i] = { ...arr[i], ...patch, updated_at: new Date().toISOString() };
      write(table, arr);
      return arr[i];
    },

    async remove(table, id) {
      const arr = read(table) || [];
      const filtered = arr.filter(x => x.id !== id);
      write(table, filtered);
      return true;
    },

    // 후기/문의 비번 검증 후 삭제
    async removeWithPassword(table, id, plainPw) {
      const arr = read(table) || [];
      const row = arr.find(x => x.id === id);
      if (!row) return { ok: false, reason: 'not_found' };
      if (!row.password_hash) return { ok: false, reason: 'no_password_set' };
      const hash = await sha256(plainPw);
      if (hash !== row.password_hash) return { ok: false, reason: 'pw_mismatch' };
      write(table, arr.filter(x => x.id !== id));
      return { ok: true };
    },

    // admin 로그인
    async adminLogin(plainPw) {
      const stored = localStorage.getItem(KEY_PREFIX + 'admin_pw_hash') || await sha256('dltjstod@9977');
      const hash = await sha256(plainPw);
      return hash === stored;
    },

    async changeAdminPassword(currentPw, newPw) {
      const ok = await this.adminLogin(currentPw);
      if (!ok) return { ok: false, reason: 'wrong_current_pw' };
      const newHash = await sha256(newPw);
      localStorage.setItem(KEY_PREFIX + 'admin_pw_hash', newHash);
      return { ok: true };
    }
  };
}

// ============================================================
// Supabase 모드 (실제 운영)
// ============================================================
function createSupabaseStore(cfg) {
  const url = cfg.SUPABASE_URL;
  const key = cfg.SUPABASE_ANON;

  // REST API 직접 (SDK 없이도 동작)
  async function req(path, opts = {}) {
    const r = await fetch(`${url}/rest/v1${path}`, {
      headers: {
        apikey: key,
        Authorization: `Bearer ${key}`,
        'Content-Type': 'application/json',
        Prefer: 'return=representation',
        ...(opts.headers || {})
      },
      ...opts
    });
    if (!r.ok) throw new Error(`Supabase ${r.status}: ${await r.text()}`);
    if (r.status === 204) return null;
    return r.json();
  }

  return {
    isDemo: false,

    async getCmsConfig() {
      const rows = await req('/cms_config?select=key,value');
      return Object.fromEntries(rows.map(r => [r.key, r.value]));
    },
    async setCmsConfig(key_, value) {
      return req(`/cms_config?key=eq.${key_}`, {
        method: 'PATCH',
        body: JSON.stringify({ value, updated_at: new Date().toISOString() })
      });
    },

    async list(table) {
      let q = '*';
      let order = 'created_at.desc';
      if (table === 'notices') order = 'pinned.desc,created_at.desc';
      if (table === 'products' || table === 'qna') order = 'sort_order.asc,created_at.desc';
      if (table === 'external_links') order = 'sort_order.asc';
      const filter = table === 'external_links' ? '&enabled=eq.true' : '';
      return req(`/${table}?select=${q}&order=${order}${filter}`);
    },

    async insert(table, row) {
      const r = await req(`/${table}`, { method: 'POST', body: JSON.stringify(row) });
      return Array.isArray(r) ? r[0] : r;
    },

    async update(table, id, patch) {
      const r = await req(`/${table}?id=eq.${id}`, {
        method: 'PATCH',
        body: JSON.stringify({ ...patch, updated_at: new Date().toISOString() })
      });
      return Array.isArray(r) ? r[0] : r;
    },

    async remove(table, id) {
      await req(`/${table}?id=eq.${id}`, { method: 'DELETE' });
      return true;
    },

    async removeWithPassword(table, id, plainPw) {
      const rows = await req(`/${table}?id=eq.${id}&select=password_hash`);
      if (!rows.length) return { ok: false, reason: 'not_found' };
      const stored = rows[0].password_hash;
      if (!stored) return { ok: false, reason: 'no_password_set' };
      const hash = await sha256(plainPw);
      if (hash !== stored) return { ok: false, reason: 'pw_mismatch' };
      await req(`/${table}?id=eq.${id}`, { method: 'DELETE' });
      return { ok: true };
    },

    async adminLogin(plainPw) {
      const rows = await req('/admin_users?id=eq.1&select=password_hash');
      if (!rows.length) return false;
      const hash = await sha256(plainPw);
      return hash === rows[0].password_hash;
    },

    async changeAdminPassword(currentPw, newPw) {
      const ok = await this.adminLogin(currentPw);
      if (!ok) return { ok: false, reason: 'wrong_current_pw' };
      const newHash = await sha256(newPw);
      await req('/admin_users?id=eq.1', {
        method: 'PATCH',
        body: JSON.stringify({ password_hash: newHash, updated_at: new Date().toISOString() })
      });
      return { ok: true };
    }
  };
}

// ============================================================
// SHA-256 유틸
// ============================================================
export async function sha256(text) {
  const enc = new TextEncoder().encode(text);
  const buf = await crypto.subtle.digest('SHA-256', enc);
  return Array.from(new Uint8Array(buf)).map(b => b.toString(16).padStart(2, '0')).join('');
}
