/**
 * Supabase project generator.
 *
 * Wrapper fino sobre generateProject().
 * A lógica de geração comum (cópia, pub get, slang, build_runner, flutterfire)
 * vive em cli/lib/scaffold/generate.js.
 *
 * Hook específico (applyBackendSetup):
 *   1. Aplica supabase/patch/ sobre o template Firebase copiado
 *   2. Substitui pubspec.yaml pelo template Supabase (pubspec.yaml.tpl)
 *   3. Remove artefatos Firebase exclusivos (ex: GoogleService-Info.plist paths)
 *   4. Escreve overrides de environment (supabaseUrl, supabaseAnonKey)
 *   5. Copia config.toml, migrations e edge-functions do backend Supabase
 */

const path = require('node:path');
const fs = require('fs-extra');
const { applyPatch, copyWithTokens } = require('../../engine');
const { generateProject } = require('../../generate');
const { writeEnvironnementsOverrides } = require('../../shared/generator-utils');
const { removeBackendSpecificArtifacts } = require('../../shared/backend-config');

const SUPABASE_PATCH_DIR = path.join(__dirname, 'patch');
const SUPABASE_PUBSPEC = path.join(__dirname, 'pubspec.yaml.tpl');
const SUPABASE_EDGE_FUNCTIONS_DIR = path.join(__dirname, 'edge-functions');
const SUPABASE_MIGRATIONS_DIR = path.join(__dirname, 'migrations');

async function generateSupabaseProject(targetDir, options) {
  const { appName, bundleId, firebaseProjectId, supabaseUrl, supabaseAnonKey } = options;

  if (!appName || !bundleId || !firebaseProjectId) {
    throw new Error('generateSupabaseProject requires appName, bundleId, firebaseProjectId');
  }
  if (!supabaseUrl || !supabaseAnonKey) {
    throw new Error('generateSupabaseProject requires supabaseUrl and supabaseAnonKey');
  }

  return generateProject(targetDir, 'supabase', options, {
    applyBackendSetup: async (dir, tokens, pathReplacements, opts) => {
      // 1. Patch Supabase (auth, storage, notifications, etc.)
      const { filesApplied } = await applyPatch(SUPABASE_PATCH_DIR, dir, tokens, pathReplacements);

      // 1b. README do backend (excluído do applyPatch) — copiar manualmente
      const language = opts.language ?? 'pt';
      const readmeLang = ['en', 'pt', 'es'].includes(language) ? language : 'en';
      const candidates = [
        path.join(SUPABASE_PATCH_DIR, `README.${readmeLang}.md`),
        path.join(SUPABASE_PATCH_DIR, 'README.md'),
      ];
      for (const src of candidates) {
        if (await fs.pathExists(src)) {
          await fs.copy(src, path.join(dir, 'README.md'));
          break;
        }
      }

      // 2. Substituir pubspec.yaml pelos deps do Supabase
      const pubspecContent = await fs.readFile(SUPABASE_PUBSPEC, 'utf8');
      let pubspecReplaced = pubspecContent;
      for (const [from, to] of Object.entries(tokens)) {
        pubspecReplaced = pubspecReplaced.replaceAll(from, to);
      }
      await fs.outputFile(path.join(dir, 'pubspec.yaml'), pubspecReplaced, 'utf8');

      // 3. Remover artefatos exclusivos do Firebase
      await removeBackendSpecificArtifacts(dir, 'supabase', opts.modules ?? []);

      // 4. Escrever overrides de environment com as credenciais Supabase
      await writeEnvironnementsOverrides(dir, 'supabase', tokens, {
        supabaseUrl: opts.supabaseUrl,
        supabaseAnonKey: opts.supabaseAnonKey,
      });

      // 5. Copiar arquivos da infraestrutura Supabase
      const supabaseDir = path.join(dir, 'supabase');
      await fs.ensureDir(supabaseDir);

      // Tokens extras para substituição nas migrations SQL
      const supabaseTokens = {
        ...tokens,
        'supabaseplaceholder.supabase.co': (opts.supabaseUrl || '').replace(/^https?:\/\//, ''),
        'sb_publishable_placeholder': opts.supabaseAnonKey || '',
      };

      const supabaseConfigPath = path.join(__dirname, 'config.toml');
      if (await fs.pathExists(supabaseConfigPath)) {
        await fs.copy(supabaseConfigPath, path.join(supabaseDir, 'config.toml'));
      }
      if (await fs.pathExists(SUPABASE_MIGRATIONS_DIR)) {
        await copyWithTokens(SUPABASE_MIGRATIONS_DIR, path.join(supabaseDir, 'migrations'), supabaseTokens);
      }
      if (await fs.pathExists(SUPABASE_EDGE_FUNCTIONS_DIR)) {
        await fs.copy(SUPABASE_EDGE_FUNCTIONS_DIR, path.join(supabaseDir, 'functions'));
      }

      return {
        detail: `${filesApplied} patch files`,
        extraAnswers: { supabaseUrl: opts.supabaseUrl, supabaseAnonKey: opts.supabaseAnonKey },
        kitSetupExtra: { supabaseUrl: opts.supabaseUrl, supabaseAnonKey: opts.supabaseAnonKey },
        returnExtra: { supabaseUrl: opts.supabaseUrl },
      };
    },

    postBuild: null,
  });
}

module.exports = { generateSupabaseProject, SUPABASE_PATCH_DIR };
