const OWNER_REPO = process.env.GITHUB_OWNER_REPO || 'latthorizon-arch/chets-schedule-site';
const BRANCH = process.env.GITHUB_BRANCH || 'main';
const TOKEN = process.env.GITHUB_WRITE_TOKEN;
const EDITOR_PASSWORD = process.env.EDITOR_PASSWORD;
const EDITOR_PASSWORD_HASH = process.env.EDITOR_PASSWORD_HASH || 'c1406a29356569fc9d7b97d3a51bcbbe99a25a1918a84424cfa699fd59c24b4d';

function send(res, code, obj) {
  res.statusCode = code;
  res.setHeader('content-type', 'application/json; charset=utf-8');
  res.end(JSON.stringify(obj));
}

function okPath(p) {
  if (!p || typeof p !== 'string') return false;
  if (p.startsWith('/') || p.includes('..') || p.includes('\\') || p.startsWith('.')) return false;
  if (p.startsWith('api/') || p.startsWith('.git/') || p.includes('/.')) return false;
  if (!/\.(html|json|css|js|txt)$/i.test(p)) return false;
  const allowed = [
    'index.html','daily.html','timesheet.html','stt.html','vacations.html','archive.html','editor.html','vercel.json',
    'months/','daily/','tickets/','stt/','assets/data/','assets/editor-config.json'
  ];
  return allowed.some(a => p === a || p.startsWith(a));
}

function sha256(s) {
  return require('crypto').createHash('sha256').update(String(s || '')).digest('hex');
}

function passwordOk(supplied) {
  if (!supplied) return false;
  if (EDITOR_PASSWORD && supplied === EDITOR_PASSWORD) return true;
  return EDITOR_PASSWORD_HASH && sha256(supplied) === EDITOR_PASSWORD_HASH;
}

function auth(req, body) {
  const supplied = (body && body.password) || req.headers['x-editor-password'] || '';
  return passwordOk(supplied);
}

async function gh(path, options = {}) {
  if (!TOKEN) throw new Error('GITHUB_WRITE_TOKEN is not configured');
  const r = await fetch(`https://api.github.com/repos/${OWNER_REPO}/contents/${encodeURIComponent(path).replace(/%2F/g,'/')}?ref=${BRANCH}`, {
    ...options,
    headers: {
      'authorization': `Bearer ${TOKEN}`,
      'accept': 'application/vnd.github+json',
      'x-github-api-version': '2022-11-28',
      'user-agent': 'chets-site-editor',
      ...(options.headers || {})
    }
  });
  const text = await r.text();
  let data = null;
  try { data = text ? JSON.parse(text) : {}; } catch { data = {raw:text}; }
  return {status:r.status, data};
}

function decodeBase64(b64) {
  return Buffer.from(String(b64 || ''), 'base64').toString('utf8');
}
function encodeBase64(s) {
  return Buffer.from(String(s || ''), 'utf8').toString('base64');
}

module.exports = async function handler(req, res) {
  try {
    if (req.method === 'GET') {
      const url = new URL(req.url, 'https://local');
      const path = url.searchParams.get('path') || '';
      const password = url.searchParams.get('password') || req.headers['x-editor-password'] || '';
      if (!passwordOk(password)) return send(res, 401, {ok:false, error:'Невірний пароль'});
      if (!okPath(path)) return send(res, 400, {ok:false, error:'Цей шлях не дозволений'});
      const got = await gh(path);
      if (got.status !== 200) return send(res, got.status, {ok:false, error: got.data.message || 'GitHub read failed'});
      return send(res, 200, {ok:true, path, sha:got.data.sha, content:decodeBase64(got.data.content)});
    }

    if (req.method !== 'POST') return send(res, 405, {ok:false, error:'Method not allowed'});
    let raw = '';
    for await (const chunk of req) raw += chunk;
    const body = raw ? JSON.parse(raw) : {};
    if (!auth(req, body)) return send(res, 401, {ok:false, error:'Невірний пароль'});
    const path = body.path || '';
    const content = String(body.content ?? '');
    if (!okPath(path)) return send(res, 400, {ok:false, error:'Цей шлях не дозволений'});
    if (content.length > 900000) return send(res, 413, {ok:false, error:'Файл занадто великий'});

    const got = await gh(path);
    let sha = body.sha || undefined;
    if (got.status === 200) sha = got.data.sha;
    else if (got.status !== 404) return send(res, got.status, {ok:false, error: got.data.message || 'GitHub read failed'});

    const commitMessage = String(body.message || `Редактор: оновлено ${path}`).slice(0, 180);
    const put = await fetch(`https://api.github.com/repos/${OWNER_REPO}/contents/${encodeURIComponent(path).replace(/%2F/g,'/')}`, {
      method:'PUT',
      headers:{
        'authorization':`Bearer ${TOKEN}`,
        'accept':'application/vnd.github+json',
        'x-github-api-version':'2022-11-28',
        'content-type':'application/json',
        'user-agent':'chets-site-editor'
      },
      body: JSON.stringify({message:commitMessage, content:encodeBase64(content), sha, branch:BRANCH})
    });
    const txt = await put.text();
    let data = {};
    try { data = txt ? JSON.parse(txt) : {}; } catch { data = {raw:txt}; }
    if (!put.ok) return send(res, put.status, {ok:false, error:data.message || 'GitHub write failed', details:data});
    return send(res, 200, {ok:true, path, commit:data.commit && data.commit.sha, html_url:data.commit && data.commit.html_url});
  } catch (e) {
    return send(res, 500, {ok:false, error:e.message || String(e)});
  }
}
