modules/frontend/Write-Frontend-RN-Feature.ps1

param(
    [string]$ProjectName,
    [string]$OutputPath,
    [string]$Platform,
    [string[]]$Entities,
    [string]$Language = "tr"
)

. (Join-Path (Split-Path $MyInvocation.MyCommand.Path) "..\core\Utils.ps1")
. (Join-Path (Split-Path $MyInvocation.MyCommand.Path) "..\core\Get-Locale.ps1")
$L = Get-Locale -Language $Language

$MobilePath = if ($Platform -eq "Both") { Join-Path $OutputPath "apps\mobile" } else { Join-Path $OutputPath "mobile" }
$AppPath = Join-Path $MobilePath "app"
$HooksPath = Join-Path $MobilePath "hooks"
$ServicesPath = Join-Path $MobilePath "services"

if (-not $Global:DryRun) {
    New-Item -ItemType Directory -Path $HooksPath -Force | Out-Null
    New-Item -ItemType Directory -Path $ServicesPath -Force | Out-Null
}

$nonUserEntities = $Entities | Where-Object { $_ -ne "User" }
$sharedImport = if ($Platform -eq "Both") { "shared" } else { "../shared" }

# 1. Write services/api.ts (Api Client instance)
$apiTs = @"
import { ApiClient } from '$sharedImport';
export const api = new ApiClient(process.env.EXPO_PUBLIC_API_URL || 'http://localhost:8080/api');
"@

Write-CoreFile (Join-Path $ServicesPath "api.ts") $apiTs

# 2. Write React Query hooks and screen components for each entity
foreach ($e in $nonUserEntities) {
    $lowE = $e.ToLower()
    $pE = Get-Plural $e
    $lowPE = $pE.ToLower()

    # Create entity directories
    if (-not $Global:DryRun) {
        New-Item -ItemType Directory -Path (Join-Path $AppPath "(tabs)\$lowPE") -Force | Out-Null
    }

    # Hooks file
    $hookContent = @"
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
import { api } from '../services/api';
 
const KEY = ['$lowPE'];
 
export function use$pE(page: number = 1, size: number = 20) {
  return useQuery({
    queryKey: [...KEY, page, size],
    queryFn: () => api.request(`/$lowPE/paged?page=\${page}&size=\${size}`),
  });
}
 
export function useAdd$e() {
  const qc = useQueryClient();
  return useMutation({
    mutationFn: (vars: { name: string; price?: number }) => api.request('/$lowPE', {
      method: 'POST',
      body: JSON.stringify(vars)
    }),
    onSuccess: () => qc.invalidateQueries({ queryKey: KEY }),
  });
}
"@

    Write-CoreFile (Join-Path $HooksPath "use$pE.ts") $hookContent

    # Entity Screen (FlatList index.tsx)
    $priceCell = if ($e -eq "Product") { " {item.price !== undefined ? `\${item.price} TL` : ''}" } else { "" }
    $indexScreen = @"
import { View, Text, FlatList, StyleSheet, TouchableOpacity, ActivityIndicator } from 'react-native';
import { useRouter } from 'expo-router';
import { use$pE } from '../../../hooks/use$pE';
import { useState } from 'react';
 
export default function ${pE}Screen() {
  const router = useRouter();
  const [page, setPage] = useState(1);
  const { data, isLoading, isError } = use$pE(page, 20);
   
  const items = data?.data?.items || [];
  const totalPages = data?.data?.totalPages || 1;
 
  return (
    <View style={styles.container}>
      <TouchableOpacity style={styles.addButton} onPress={() => router.push('/$lowPE/add')}>
        <Text style={styles.addButtonText}>+ $($L.uiNewEntity -f $e)</Text>
      </TouchableOpacity>
 
      {isLoading ? (
        <ActivityIndicator size="large" color="#3b82f6" style={{ marginTop: 40 }} />
      ) : (
        <FlatList
          data={items}
          keyExtractor={(item: any) => item.id.toString()}
          style={styles.list}
          renderItem={({ item }: { item: any }) => (
            <View style={styles.itemCard}>
              <Text style={styles.itemText}>{item.name}</Text>
$priceCell </View>
          )}
          ListEmptyComponent={
            <Text style={styles.emptyText}>$($L.uiNoData)</Text>
          }
        />
      )}
 
      <View style={styles.pagination}>
        <TouchableOpacity
          style={[styles.pageButton, page === 1 && styles.disabled]}
          disabled={page === 1}
          onPress={() => setPage(p => Math.max(1, p - 1))}
        >
          <Text style={styles.pageButtonText}>$($L.uiPrevious)</Text>
        </TouchableOpacity>
         
        <Text style={styles.pageInfo}>$($L.uiPage -f '{page}', '{totalPages}')</Text>
 
        <TouchableOpacity
          style={[styles.pageButton, page >= totalPages && styles.disabled]}
          disabled={page >= totalPages}
          onPress={() => setPage(p => Math.min(totalPages, p + 1))}
        >
          <Text style={styles.pageButtonText}>$($L.uiNext)</Text>
        </TouchableOpacity>
      </View>
    </View>
  );
}
 
const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#121212',
    padding: 16,
  },
  addButton: {
    backgroundColor: '#3b82f6',
    padding: 14,
    borderRadius: 8,
    alignItems: 'center',
    marginBottom: 16,
  },
  addButtonText: {
    color: '#ffffff',
    fontWeight: 'bold',
    fontSize: 16,
  },
  list: {
    flex: 1,
  },
  itemCard: {
    backgroundColor: '#1e1e1e',
    padding: 16,
    borderRadius: 8,
    marginBottom: 10,
    borderWidth: 1,
    borderColor: '#333333',
    flexDirection: 'row',
    justifyContent: 'space-between',
    alignItems: 'center',
  },
  itemText: {
    color: '#ffffff',
    fontSize: 16,
    fontWeight: '500',
  },
  itemSub: {
    color: '#10b981',
    fontWeight: '600',
  },
  emptyText: {
    color: '#888888',
    textAlign: 'center',
    marginTop: 40,
    fontSize: 15,
  },
  pagination: {
    flexDirection: 'row',
    justifyContent: 'space-between',
    alignItems: 'center',
    marginTop: 10,
  },
  pageButton: {
    backgroundColor: '#1e1e1e',
    paddingVertical: 10,
    paddingHorizontal: 16,
    borderRadius: 6,
  },
  pageButtonText: {
    color: '#ffffff',
    fontWeight: '600',
  },
  disabled: {
    opacity: 0.5,
  },
  pageInfo: {
    color: '#888888',
  },
});
"@

    Write-CoreFile (Join-Path $AppPath "(tabs)\$lowPE\index.tsx") $indexScreen

    # Entity Add Screen (add.tsx)
    $priceFieldState = if ($e -eq "Product") { " const [price, setPrice] = useState('');" } else { "" }
    $priceInputMarkup = if ($e -eq "Product") { @"
      <Text style={styles.label}>$($L.uiPrice)</Text>
      <TextInput
        style={styles.input}
        value={price}
        onChangeText={setPrice}
        keyboardType="numeric"
        placeholder="0.00"
        placeholderTextColor="#666666"
      />
"@
 } else { "" }
    $mutatePayload = if ($e -eq "Product") { "{ name, price: parseFloat(price) || 0 }" } else { "{ name }" }

    $addScreen = @"
import { View, Text, TextInput, StyleSheet, TouchableOpacity, ActivityIndicator, Alert } from 'react-native';
import { useRouter } from 'expo-router';
import { useState } from 'react';
import { useAdd$e } from '../../../hooks/use$pE';
 
export default function Add${e}Screen() {
  const router = useRouter();
  const [name, setName] = useState('');
$priceFieldState
  const addMutation = useAdd$e();
 
  const handleSubmit = async () => {
    if (!name.trim()) {
      Alert.alert('Error', 'Name is required.');
      return;
    }
    try {
      await addMutation.mutateAsync($mutatePayload);
      Alert.alert('Success', '$($L.uiEntityAdded -f $e)');
      router.back();
    } catch (err: any) {
      Alert.alert('Error', err.message || '$($L.uiAddFailed)');
    }
  };
 
  return (
    <View style={styles.container}>
      <Text style={styles.label}>$($L.uiEntityName -f $e)</Text>
      <TextInput
        style={styles.input}
        value={name}
        onChangeText={setName}
        placeholder="Name"
        placeholderTextColor="#666666"
      />
 
$priceInputMarkup
      <TouchableOpacity
        style={[styles.saveButton, addMutation.isPending && styles.disabled]}
        onPress={handleSubmit}
        disabled={addMutation.isPending}
      >
        {addMutation.isPending ? (
          <ActivityIndicator color="#ffffff" />
        ) : (
          <Text style={styles.saveButtonText}>$($L.uiAdd)</Text>
        )}
      </TouchableOpacity>
    </View>
  );
}
 
const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#121212',
    padding: 20,
  },
  label: {
    color: '#ffffff',
    fontSize: 16,
    fontWeight: '600',
    marginBottom: 8,
    marginTop: 12,
  },
  input: {
    backgroundColor: '#1e1e1e',
    color: '#ffffff',
    padding: 14,
    borderRadius: 8,
    fontSize: 16,
    borderWidth: 1,
    borderColor: '#333333',
  },
  saveButton: {
    backgroundColor: '#3b82f6',
    padding: 14,
    borderRadius: 8,
    alignItems: 'center',
    marginTop: 30,
  },
  saveButtonText: {
    color: '#ffffff',
    fontWeight: 'bold',
    fontSize: 16,
  },
  disabled: {
    opacity: 0.7,
  },
});
"@

    Write-CoreFile (Join-Path $AppPath "(tabs)\$lowPE\add.tsx") $addScreen
}