"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.generateCode = generateCode;
const path_1 = __importDefault(require("path"));
const fs_extra_1 = __importDefault(require("fs-extra"));
// ---------------------------------------------------------------------------
// Project context detection
// ---------------------------------------------------------------------------
async function detectProjectConfig() {
    let dir = process.cwd();
    const root = path_1.default.parse(dir).root;
    while (dir !== root) {
        const pkgPath = path_1.default.join(dir, "package.json");
        if (await fs_extra_1.default.pathExists(pkgPath)) {
            const pkg = await fs_extra_1.default.readJson(pkgPath);
            if (pkg.rnstarterkitConfig) {
                return { config: pkg.rnstarterkitConfig, projectRoot: dir };
            }
        }
        dir = path_1.default.dirname(dir);
    }
    throw new Error("❌ No rnstarterkitConfig found in package.json.\n" +
        "   Run this command from inside a project created with create-rnstarterkit.");
}
// ---------------------------------------------------------------------------
// Helpers
// ---------------------------------------------------------------------------
function toPascalCase(str) {
    return str.charAt(0).toUpperCase() + str.slice(1);
}
function toCamelCase(str) {
    return str.charAt(0).toLowerCase() + str.slice(1);
}
async function writeAndLog(filePath, content) {
    if (await fs_extra_1.default.pathExists(filePath)) {
        console.error(`❌ File already exists: ${filePath}`);
        process.exit(1);
    }
    await fs_extra_1.default.ensureDir(path_1.default.dirname(filePath));
    await fs_extra_1.default.writeFile(filePath, content, "utf8");
    console.log(`✅ Created ${path_1.default.relative(process.cwd(), filePath)}`);
}
// ---------------------------------------------------------------------------
// screen generator
// ---------------------------------------------------------------------------
function screenStateImports(config) {
    if (!config.auth)
        return "";
    if (config.state === "Redux Toolkit") {
        return `import { useAppSelector } from '../store/hooks';\n`;
    }
    if (config.state === "Zustand") {
        return `import { useAuthStore } from '../store/authStore';\n`;
    }
    if (config.state === "Context API") {
        return `import { useContext } from 'react';\nimport { AuthContext } from '../context/AuthContext';\n`;
    }
    return "";
}
function screenStateHook(config) {
    if (!config.auth)
        return "";
    if (config.state === "Redux Toolkit") {
        return `\n  const token = useAppSelector((state) => state.auth.token);\n`;
    }
    if (config.state === "Zustand") {
        return `\n  const { token } = useAuthStore();\n`;
    }
    if (config.state === "Context API") {
        return `\n  const { token } = useContext(AuthContext);\n`;
    }
    return "";
}
async function generateScreen(name, config, projectRoot) {
    const screenName = toPascalCase(name);
    const fileName = `${screenName}Screen.tsx`;
    const targetDir = config.platform === "Expo"
        ? path_1.default.join(projectRoot, "app")
        : path_1.default.join(projectRoot, "screens");
    const filePath = path_1.default.join(targetDir, fileName);
    const stateImports = screenStateImports(config);
    const stateHook = screenStateHook(config);
    const layoutImport = config.platform === "React Native CLI"
        ? `import ScreenLayout from '../components/layout/ScreenLayout';\n`
        : "";
    const wrapper = config.platform === "React Native CLI"
        ? ["<ScreenLayout>", "    </ScreenLayout>"]
        : ["<View style={styles.container}>", "    </View>"];
    const content = config.platform === "Expo"
        ? `import React from 'react';
import { View, Text, StyleSheet } from 'react-native';
${stateImports}
export default function ${screenName}Screen() {${stateHook}
  return (
    ${wrapper[0]}
      <Text style={styles.title}>${screenName}</Text>
    ${wrapper[1]}
  );
}

const styles = StyleSheet.create({
  container: { flex: 1, alignItems: 'center', justifyContent: 'center', padding: 20 },
  title: { fontSize: 24, fontWeight: 'bold', color: '#111827' },
});
`
        : `import React from 'react';
import { Text, StyleSheet } from 'react-native';
${layoutImport}${stateImports}
export default function ${screenName}Screen() {${stateHook}
  return (
    ${wrapper[0]}
      <Text style={styles.title}>${screenName}</Text>
    ${wrapper[1]}
  );
}

const styles = StyleSheet.create({
  title: { fontSize: 24, fontWeight: 'bold', color: '#111827' },
});
`;
    await writeAndLog(filePath, content);
}
// ---------------------------------------------------------------------------
// component generator
// ---------------------------------------------------------------------------
async function generateComponent(name, projectRoot) {
    const componentName = toPascalCase(name);
    const filePath = path_1.default.join(projectRoot, "components", `${componentName}.tsx`);
    const content = `import React from 'react';
import { View, Text, StyleSheet, type ViewStyle } from 'react-native';

type ${componentName}Props = {
  label?: string;
  style?: ViewStyle;
};

export function ${componentName}({ label = '${componentName}', style }: ${componentName}Props) {
  return (
    <View style={[styles.container, style]}>
      <Text style={styles.label}>{label}</Text>
    </View>
  );
}

const styles = StyleSheet.create({
  container: { padding: 12 },
  label: { fontSize: 14, color: '#374151' },
});
`;
    await writeAndLog(filePath, content);
}
// ---------------------------------------------------------------------------
// hook generator
// ---------------------------------------------------------------------------
async function generateHook(name, projectRoot) {
    const baseName = name.startsWith("use") ? name.slice(3) : name;
    const hookName = `use${toPascalCase(baseName)}`;
    const filePath = path_1.default.join(projectRoot, "hooks", `${hookName}.ts`);
    const content = `import { useState, useCallback } from 'react';

type ${toPascalCase(baseName)}State = {
  data: null;
  isLoading: boolean;
  error: string | null;
};

export function ${hookName}() {
  const [state, setState] = useState<${toPascalCase(baseName)}State>({
    data: null,
    isLoading: false,
    error: null,
  });

  const execute = useCallback(async () => {
    setState((prev) => ({ ...prev, isLoading: true, error: null }));
    try {
      // TODO: implement hook logic
      setState((prev) => ({ ...prev, isLoading: false }));
    } catch (err) {
      setState((prev) => ({
        ...prev,
        isLoading: false,
        error: err instanceof Error ? err.message : 'Unknown error',
      }));
    }
  }, []);

  return { ...state, execute };
}
`;
    await writeAndLog(filePath, content);
}
// ---------------------------------------------------------------------------
// slice generator
// ---------------------------------------------------------------------------
async function generateSlice(name, config, projectRoot) {
    if (config.state !== "Redux Toolkit") {
        console.error(`❌ Slice generation requires Redux Toolkit. This project uses: ${config.state || "None"}`);
        process.exit(1);
    }
    const sliceName = toCamelCase(name);
    const SliceName = toPascalCase(name);
    const filePath = path_1.default.join(projectRoot, "store", `${sliceName}Slice.ts`);
    // --- write the slice file ---
    const sliceContent = `import { createSlice, type PayloadAction } from '@reduxjs/toolkit';

interface ${SliceName}State {
  // TODO: define your state shape
  data: null;
  isLoading: boolean;
  error: string | null;
}

const initialState: ${SliceName}State = {
  data: null,
  isLoading: false,
  error: null,
};

const ${sliceName}Slice = createSlice({
  name: '${sliceName}',
  initialState,
  reducers: {
    setLoading(state, _action: PayloadAction<boolean>) {
      state.isLoading = _action.payload;
    },
    setError(state, action: PayloadAction<string | null>) {
      state.error = action.payload;
    },
    reset() {
      return initialState;
    },
  },
});

export const { setLoading, setError, reset } = ${sliceName}Slice.actions;
export default ${sliceName}Slice.reducer;
`;
    await writeAndLog(filePath, sliceContent);
    // --- patch store.ts to register the new reducer ---
    const storePath = path_1.default.join(projectRoot, "store", "store.ts");
    if (await fs_extra_1.default.pathExists(storePath)) {
        let storeContent = await fs_extra_1.default.readFile(storePath, "utf8");
        const importLine = `import ${sliceName}Reducer from './${sliceName}Slice';\n`;
        if (!storeContent.includes(importLine)) {
            // Add import after last existing import
            storeContent = storeContent.replace(/^(import .+\n)+/m, (match) => `${match}${importLine}`);
        }
        // Add reducer key inside configureStore reducer object
        if (!storeContent.includes(`${sliceName}:`)) {
            storeContent = storeContent.replace(/reducer:\s*\{/, `reducer: {\n    ${sliceName}: ${sliceName}Reducer,`);
        }
        await fs_extra_1.default.writeFile(storePath, storeContent, "utf8");
        console.log(`🔗 Registered ${sliceName} in store/store.ts`);
    }
    else {
        console.warn(`⚠️  store/store.ts not found — add the reducer manually:\n` +
            `   import ${sliceName}Reducer from './${sliceName}Slice';\n` +
            `   // add ${sliceName}: ${sliceName}Reducer to your store`);
    }
}
// ---------------------------------------------------------------------------
// Public entry point
// ---------------------------------------------------------------------------
async function generateCode(type, name) {
    const { config, projectRoot } = await detectProjectConfig();
    const validTypes = ["screen", "component", "hook", "slice"];
    if (!validTypes.includes(type)) {
        console.error(`❌ Unknown type "${type}". Valid types: ${validTypes.join(" | ")}`);
        process.exit(1);
    }
    switch (type) {
        case "screen":
            await generateScreen(name, config, projectRoot);
            break;
        case "component":
            await generateComponent(name, projectRoot);
            break;
        case "hook":
            await generateHook(name, projectRoot);
            break;
        case "slice":
            await generateSlice(name, config, projectRoot);
            break;
    }
}
