
"use server";
import { z } from "zod";
import { collection, addDoc, serverTimestamp, doc, getDoc, updateDoc, deleteDoc, Timestamp, setDoc, query, orderBy, limit, getDocs, where, writeBatch } from "firebase/firestore";
import { db } from "@/lib/firebase"; // Ensure db is correctly imported
import { revalidatePath } from "next/cache";
import { TARI_PROJECT_IMAGES_FOLDER, LOGO_URL, TARI_GENERAL_IMAGES_FOLDER, TARI_SITE_ASSETS_FOLDER, KEY_PROJECTS_SEED_DATA } from "@/constants";
import type { TariFile, SiteSettings, Project as ProjectType } from "@/types";


// Tari API Configuration
const TARI_API_BASE_URL = "https://files.tari.africa/api.php";

// In-memory cache for Tari API Bearer token
let tariApiTokenCache = {
  token: null as string | null,
  expiresAt: 0 as number, // Stores the timestamp (in ms) when the token expires
};

async function getTariApiToken(): Promise<string> {
  const now = Date.now();

  // console.log("Server: getTariApiToken called. Cache expiresAt:", new Date(tariApiTokenCache.expiresAt).toISOString(), "Now:", new Date(now).toISOString());
  if (tariApiTokenCache.token && tariApiTokenCache.expiresAt > now) {
    // console.log("Server: Using cached Tari API Bearer token.");
    return tariApiTokenCache.token;
  }

  const username = process.env.TARI_USERNAME;
  const password = process.env.TARI_PASSWORD;

  // console.log(`Server: Attempting to fetch new Tari API token with username: ${username ? username.substring(0, 3) + '...' : 'USERNAME_UNDEFINED'}`);

  if (!username) {
    console.error("Server: getTariApiToken - TARI_USERNAME is not configured in .env. Cannot authenticate with Tari API.");
    throw new Error("Tari API username not configured. Server-side setup required.");
  }
  if (!password) {
    console.error("Server: getTariApiToken - TARI_PASSWORD is not configured in .env. Cannot authenticate with Tari API.");
    throw new Error("Tari API password not configured. Server-side setup required.");
  }

  // console.log("Server: Fetching new Tari API token from " + `${TARI_API_BASE_URL}?path=auth`);

  try {
    const authResponse = await fetch(`${TARI_API_BASE_URL}?path=auth`, {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ username, password }),
      cache: 'no-store', // Ensure fresh auth request
    });

    const responseBodyText = await authResponse.text();
    // console.log("Server: Tari API auth raw response text:", responseBodyText);

    if (!authResponse.ok) {
      console.error(`Server: getTariApiToken - Tari API authentication request failed: ${authResponse.status} ${authResponse.statusText}. Body: ${responseBodyText}`);
      tariApiTokenCache.token = null;
      tariApiTokenCache.expiresAt = 0;
      throw new Error(`Tari API authentication request failed: ${authResponse.statusText} - ${responseBodyText}`);
    }

    let authResult;
    try {
      authResult = JSON.parse(responseBodyText);
    } catch (parseError: any) {
      console.error("Server: getTariApiToken - Tari API authentication error: Failed to parse JSON response.", parseError.message, "Raw response:", responseBodyText);
      tariApiTokenCache.token = null;
      tariApiTokenCache.expiresAt = 0;
      throw new Error(`Tari API authentication error: Malformed JSON response - ${parseError.message}`);
    }
    // console.log("Server: Parsed Tari API auth result:", authResult);

    if (!authResult.success || typeof authResult.token !== 'string' || !authResult.token.trim()) {
      const errorMsg = authResult.error || "'token' field is missing, not a string, or empty in auth response.";
      console.error(`Server: getTariApiToken - Tari API authentication failed: ${errorMsg}`, authResult);
      tariApiTokenCache.token = null;
      tariApiTokenCache.expiresAt = 0;
      throw new Error(`Tari API authentication failed: ${errorMsg}`);
    }
    
    tariApiTokenCache.token = authResult.token;

    if (typeof authResult.expires_in === 'number' && authResult.expires_in > 0) {
        const expiresInMs = (authResult.expires_in - (5 * 60)) * 1000; 
        tariApiTokenCache.expiresAt = now + expiresInMs;
        // console.log(`Server: Successfully fetched and cached new Tari API Bearer token. Expires in: ${authResult.expires_in}s. Cache expires at: ${new Date(tariApiTokenCache.expiresAt).toISOString()}`);
    } else {
        console.warn("Server: getTariApiToken - Tari API auth response did not contain a valid 'expires_in' (duration in seconds). Defaulting token cache expiry to 55 minutes. Auth Response:", authResult);
        tariApiTokenCache.expiresAt = now + (55 * 60 * 1000);
    }
    
    return tariApiTokenCache.token;

  } catch (error: any) {
    console.error("Server: getTariApiToken - Error during Tari API token fetch operation:", error.message, error);
    tariApiTokenCache.token = null;
    tariApiTokenCache.expiresAt = 0;
    throw error; 
  }
}

export async function fetchAndReturnTariToken(): Promise<{ token: string | null; error?: string }> {
  try {
    const token = await getTariApiToken();
    return { token };
  } catch (error: any) {
    console.error("Server: fetchAndReturnTariToken - Failed to get Tari token", error.message);
    return { token: null, error: error.message || "Failed to fetch Tari API token." };
  }
}

interface TariUploadFileDetails {
  name: string;
  path: string;
  url: string;
  public_url: string;
  size: number;
  type: string;
  modified: string;
}

interface TariUploadResponse {
  success: boolean;
  message?: string;
  file?: TariUploadFileDetails; 
  error?: string;
  [key: string]: any;
}

async function uploadImageToTari(imageFile: File, folder: string): Promise<{ url: string, path: string }> {
  let token: string;
  try {
    token = await getTariApiToken();
    if (!token || typeof token !== 'string' || !token.trim()) {
      console.error("Server: uploadImageToTari - Obtained Tari token is invalid or empty.");
      throw new Error("Failed to obtain a valid Tari API token for upload.");
    }
  } catch (authError: any) {
    console.error("Server: uploadImageToTari - Failed to obtain Tari API token before upload.", authError.message);
    throw new Error(`Failed to obtain Tari API token for upload: ${authError.message}`);
  }
  // console.log(`Server: Token used for Tari upload (folder: ${folder}, first 10 chars of token): ${token.substring(0, 10)}...`);

  const formData = new FormData();
  formData.append('files[]', imageFile, imageFile.name);
  formData.append('folder', folder);

  const authorizationHeader = `Bearer ${token}`;
  // console.log(`Server: uploadImageToTari - Authorization header for upload: ${authorizationHeader.substring(0,15)}...`);

  let response;
  try {
    response = await fetch(`${TARI_API_BASE_URL}?path=upload`, {
      method: 'POST',
      headers: { 'Authorization': authorizationHeader },
      body: formData,
      cache: 'no-store',
    });
  } catch (fetchError: any) {
    console.error(`Server: uploadImageToTari - Network error during Tari API upload: ${fetchError.message}`, fetchError);
    throw new Error(`Network error during Tari API upload: ${fetchError.message}`);
  }
  
  const responseBodyText = await response.text();
  // console.log(`Server: Tari API upload raw response for file "${imageFile.name}" to folder "${folder}": ${responseBodyText}`);

  if (!response.ok) {
    let detailedErrorMessage = responseBodyText;
    try {
      const parsedError = JSON.parse(responseBodyText);
      if (parsedError && parsedError.error) {
        detailedErrorMessage = `${parsedError.error}${parsedError.code ? ` (Code: ${parsedError.code})` : ''}`;
      }
    } catch (e) { /* Ignore parsing error, use raw text */ }
    console.error(`Server: uploadImageToTari - Tari API upload request failed: ${response.status} ${response.statusText} - ${detailedErrorMessage}`);
    throw new Error(`Tari API upload failed: ${response.statusText} - ${detailedErrorMessage}`);
  }

  let result: TariUploadResponse;
  try {
    result = JSON.parse(responseBodyText);
  } catch (parseError: any) {
    console.error(`Server: uploadImageToTari - Malformed JSON response from Tari API upload: ${parseError.message}. Raw: ${responseBodyText}`);
    throw new Error(`Tari API upload error: Malformed JSON response - ${parseError.message}`);
  }

  if (!result.success || !result.file || !result.file.public_url || !result.file.path) {
    const errorDetail = result.error || result.message || 'Essential file details (public_url, path from result.file) missing in upload response.';
    console.error("Server: uploadImageToTari - Tari API upload error. Result:", result);
    throw new Error(`Tari API upload error: ${errorDetail}`);
  }
  // console.log("Server: uploadImageToTari - Image uploaded successfully to Tari. Path:", result.file.path, "Public URL:", result.file.public_url);
  return { url: result.file.public_url, path: result.file.path };
}


async function deleteImageFromTari(filePath: string): Promise<{success: boolean, message: string}> {
  if (!filePath || typeof filePath !== 'string' || filePath.trim() === '') {
    // console.log("Server: deleteImageFromTari - No valid file path provided, skipping deletion.");
    return { success: true, message: "No valid file path provided, skipping deletion." };
  }
  let token: string;
  try {
    token = await getTariApiToken();
    if (!token || typeof token !== 'string' || !token.trim()) {
      throw new Error("Server: deleteImageFromTari - Obtained token is invalid or empty.");
    }
  } catch (authError: any) {
    // console.error("Server: deleteImageFromTari - Failed to obtain Tari API token for deletion.", authError.message);
    return { success: false, message: `Failed to obtain Tari API token for deletion: ${authError.message}`};
  }

  const authorizationHeader = `Bearer ${token}`;
  // console.log(`Server: Attempting to delete image from Tari. Path: ${filePath}. Token (first 10): ${token.substring(0,10)}...`);

  try {
    const response = await fetch(`${TARI_API_BASE_URL}?path=file`, {
      method: 'DELETE',
      headers: {
        'Content-Type': 'application/json',
        'Authorization': authorizationHeader
      },
      body: JSON.stringify({ file: filePath }),
      cache: 'no-store',
    });

    const responseBodyText = await response.text();
    // console.log(`Server: Tari API delete raw response for path '${filePath}': ${responseBodyText}`);

    if (!response.ok) {
      let errorDetail = responseBodyText;
      try {
        const parsedError = JSON.parse(responseBodyText);
        if (parsedError && parsedError.error) {
          errorDetail = parsedError.error;
        }
      } catch (e) { /* use raw text */ }
      // console.error(`Server: deleteImageFromTari - Tari API delete request failed: ${response.statusText} - ${errorDetail}`);
      return { success: false, message: `Tari API delete failed: ${response.statusText} - ${errorDetail}` };
    }
    const result = JSON.parse(responseBodyText);
    if (result.success) {
      // console.log(`Server: deleteImageFromTari - File '${filePath}' deleted successfully from Tari.`);
      return { success: true, message: "File deleted successfully from Tari." };
    } else {
      // console.warn(`Server: deleteImageFromTari - Tari API reported failure deleting '${filePath}': ${result.error || 'Unknown error'}`);
      return { success: false, message: `Tari API reported failure deleting: ${result.error || 'Unknown error'}` };
    }
  } catch (error: any) {
    // console.error(`Server: deleteImageFromTari - Error during Tari API delete operation for '${filePath}':`, error.message, error);
    return { success: false, message: `Error during Tari API delete: ${error.message}` };
  }
}

// --- Newsletter Subscription ---
const NewsletterSubscriptionSchema = z.object({
  email: z.string().email({ message: "Please enter a valid email address." }),
});
export type NewsletterFormState = { message: string; success?: boolean; errors?: { email?: string[] }; };
export async function subscribeToNewsletter(prevState: NewsletterFormState, formData: FormData): Promise<NewsletterFormState> {
  const validatedFields = NewsletterSubscriptionSchema.safeParse({ email: formData.get("email") });
  if (!validatedFields.success) return { message: "Invalid email.", errors: validatedFields.error.flatten().fieldErrors };
  const email = validatedFields.data.email;
  try {
    await new Promise(resolve => setTimeout(resolve, 1000));
    return { message: `Thank you for subscribing, ${email}!`, success: true };
  } catch (error) {
    return { message: "Subscription failed. Please try again later.", success: false };
  }
}

// --- Contact Form Submission ---
const serviceTitles = ["General Inquiry", "Enterprise Development Services", "Financial Inclusion", "Digital Innovation", "Experiential Marketing"];
const ContactFormSchema = z.object({
  name: z.string().min(2, { message: "Name must be at least 2 characters." }),
  email: z.string().email({ message: "Please enter a valid email address." }),
  subject: z.enum(serviceTitles as [string, ...string[]], {
    errorMap: () => ({ message: "Please select a valid subject." }),
  }),
  message: z.string().min(10, { message: "Message must be at least 10 characters." }),
});
export type ContactFormState = { message: string; success?: boolean; errors?: { name?: string[]; email?: string[]; subject?: string[]; message?: string[]; }; };
export async function submitContactForm(prevState: ContactFormState, formData: FormData): Promise<ContactFormState> {
  const validatedFields = ContactFormSchema.safeParse(Object.fromEntries(formData.entries()));
  if (!validatedFields.success) return { message: "Invalid form data.", errors: validatedFields.error.flatten().fieldErrors };
  await new Promise(resolve => setTimeout(resolve, 1500));
  return { message: "Thank you for your message! We'll be in touch soon.", success: true };
}

// --- Project Management Actions ---
const MAX_FILE_SIZE_PROJECTS = 5 * 1024 * 1024;
const ACCEPTED_IMAGE_TYPES_PROJECTS = ["image/jpeg", "image/jpg", "image/png", "image/webp"];

const AddProjectServerSchema = z.object({
  title: z.string().min(3, "Title must be at least 3 characters."),
  organization: z.string().min(3, "Organization must be at least 3 characters."),
  description: z.string().min(10, "Description must be at least 10 characters."),
  imageHint: z.string().min(2, "Image hint must be at least 2 characters.").max(50, "Image hint is too long."),
  impact: z.string().min(1, "Impact points required.").transform(val => val.split(',').map(s => s.trim()).filter(Boolean)),
});
export type AddProjectFormState = { message: string; success?: boolean; errors?: { title?: string[]; organization?: string[]; description?: string[]; imageFile?: string[]; imageHint?: string[]; impact?: string[]; general?: string[]; }; };

export async function addProject(prevState: AddProjectFormState, formData: FormData): Promise<AddProjectFormState> {
  try {
    const imageFile = formData.get("imageFile") as File | null;
    const textFields = {
      title: formData.get("title"),
      organization: formData.get("organization"),
      description: formData.get("description"),
      imageHint: formData.get("imageHint"),
      impact: formData.get("impact"),
    };
    const validatedFields = AddProjectServerSchema.safeParse(textFields);

    if (!validatedFields.success) {
      return { message: "Invalid project data.", errors: validatedFields.error.flatten().fieldErrors, success: false };
    }
    if (!imageFile || imageFile.size === 0) {
      return { message: "Image file is required.", errors: { imageFile: ["Please upload an image."] }, success: false };
    }
    if (imageFile.size > MAX_FILE_SIZE_PROJECTS) {
      return { message: `Max file size is ${MAX_FILE_SIZE_PROJECTS / (1024*1024)}MB.`, errors: { imageFile: [`Max file size is ${MAX_FILE_SIZE_PROJECTS / (1024*1024)}MB.`] }, success: false };
    }
    if (!ACCEPTED_IMAGE_TYPES_PROJECTS.includes(imageFile.type)) {
      return { message: "Invalid image type.", errors: { imageFile: ["Only .jpg, .jpeg, .png and .webp formats are supported."] }, success: false };
    }

    const { title, organization, description, imageHint, impact } = validatedFields.data;
    let tariImageData: { url: string; path: string };

    try {
      tariImageData = await uploadImageToTari(imageFile, TARI_PROJECT_IMAGES_FOLDER);
    } catch (uploadError: any) {
      return { message: `Failed to upload image: ${uploadError.message}`, errors: { general: [uploadError.message] }, success: false };
    }

    await addDoc(collection(db, "projects"), {
      title, organization, description,
      imageUrl: tariImageData.url,
      imagePathTari: tariImageData.path,
      imageHint, impact,
      createdAt: serverTimestamp(),
    });

    revalidatePath('/staff-portal/dashboard/admin-projects');
    revalidatePath('/projects');
    revalidatePath('/');
    return { message: "Project added successfully! Image uploaded to Tari.", success: true };

  } catch (error: any) {
    const errorMessage = (error instanceof Error ? error.message : String(error)) || 'An unexpected server error occurred adding project.';
    console.error("Server: addProject - Error:", errorMessage, error);
    return { message: `Server error: ${errorMessage}`, success: false, errors: { general: [errorMessage] } };
  }
}

export type DeleteProjectState = { success: boolean; message: string; };
export async function deleteProject(projectId: string): Promise<DeleteProjectState> {
  if (!projectId) return { success: false, message: "Project ID is missing." };
  try {
    const projectRef = doc(db, "projects", projectId);
    const projectSnap = await getDoc(projectRef);
    if (!projectSnap.exists()) return { success: false, message: "Project not found." };

    const projectData = projectSnap.data();
    if (projectData?.imagePathTari && typeof projectData.imagePathTari === 'string' && projectData.imagePathTari.trim() !== '') {
      const deleteResult = await deleteImageFromTari(projectData.imagePathTari);
      if (!deleteResult.success) {
        console.warn(`Failed to delete image from Tari for project ${projectId}: ${deleteResult.message}`);
      }
    }

    await deleteDoc(projectRef);
    revalidatePath('/staff-portal/dashboard/admin-projects');
    revalidatePath('/projects');
    revalidatePath('/');
    revalidatePath(`/projects/${projectId}`);
    return { success: true, message: "Project deleted. Associated image (if any on Tari) also attempted for deletion." };
  } catch (error: any) {
    console.error("Server: deleteProject - Error:", error.message, error);
    return { success: false, message: `Failed to delete project: ${error.message}` };
  }
}

const UpdateProjectServerSchema = AddProjectServerSchema;
export type UpdateProjectFormState = AddProjectFormState;

export async function updateProject(projectId: string, prevState: UpdateProjectFormState, formData: FormData): Promise<UpdateProjectFormState> {
  if (!projectId) return { message: "Project ID missing.", success: false };
  try {
    const imageFile = formData.get("imageFile") as File | null;
    const textFields = {
      title: formData.get("title"),
      organization: formData.get("organization"),
      description: formData.get("description"),
      imageHint: formData.get("imageHint"),
      impact: formData.get("impact"),
    };
    const validatedFields = UpdateProjectServerSchema.safeParse(textFields);

    if (!validatedFields.success) {
      return { message: "Invalid project data.", errors: validatedFields.error.flatten().fieldErrors, success: false };
    }

    const projectRef = doc(db, "projects", projectId);
    const projectSnap = await getDoc(projectRef);
    if (!projectSnap.exists()) return { message: "Project not found.", success: false };

    const existingData = projectSnap.data();
    const updateData: any = { ...validatedFields.data, updatedAt: serverTimestamp() };

    if (imageFile && imageFile.size > 0) {
      if (imageFile.size > MAX_FILE_SIZE_PROJECTS) return { message: `Max file size is ${MAX_FILE_SIZE_PROJECTS / (1024*1024)}MB.`, errors: { imageFile: [`Max file size is ${MAX_FILE_SIZE_PROJECTS / (1024*1024)}MB.`] }, success: false };
      if (!ACCEPTED_IMAGE_TYPES_PROJECTS.includes(imageFile.type)) return { message: "Invalid image type.", errors: { imageFile: ["Only .jpg, .jpeg, .png and .webp formats are supported."] }, success: false };

      try {
        if (existingData?.imagePathTari && typeof existingData.imagePathTari === 'string' && existingData.imagePathTari.trim() !== '') {
          await deleteImageFromTari(existingData.imagePathTari);
        }
        const newTariImageData = await uploadImageToTari(imageFile, TARI_PROJECT_IMAGES_FOLDER);
        updateData.imageUrl = newTariImageData.url;
        updateData.imagePathTari = newTariImageData.path;
      } catch (imageHandlingError: any) {
        return { message: `Failed to update image: ${imageHandlingError.message}`, errors: { general: [imageHandlingError.message] }, success: false };
      }
    } else {
      updateData.imageUrl = existingData?.imageUrl;
      updateData.imagePathTari = existingData?.imagePathTari;
    }

    await updateDoc(projectRef, updateData);
    revalidatePath('/staff-portal/dashboard/admin-projects');
    revalidatePath('/projects');
    revalidatePath('/');
    revalidatePath(`/projects/${projectId}`);
    return { message: "Project updated successfully!", success: true };
  } catch (error: any) {
    const errorMessage = (error instanceof Error ? error.message : String(error)) || 'An unexpected server error occurred updating project.';
    console.error("Server: updateProject - Error:", errorMessage, error);
    return { message: `Server error: ${errorMessage}`, success: false, errors: { general: [errorMessage] } };
  }
}

// --- General Image Management Actions (Tari API) ---
export type ListTariImagesState = { success: boolean; files?: TariFile[]; error?: string; };
export async function listTariImages(folderPath: string = TARI_GENERAL_IMAGES_FOLDER): Promise<ListTariImagesState> {
  let token: string;
  try {
    token = await getTariApiToken();
     if (!token || typeof token !== 'string' || !token.trim()) {
        console.error("Server: listTariImages - A valid Tari API token could not be retrieved (token is empty or invalid).");
        return { success: false, error: "A valid Tari API token could not be retrieved for listing images (token empty/invalid)." };
    }
  } catch (authError: any) {
    console.error("Server: listTariImages - Authentication failed for Tari API:", authError.message, authError);
    return { success: false, error: `Authentication failed for Tari API: ${authError.message || 'Unknown authentication error'}` };
  }

  const authorizationHeader = `Bearer ${token}`;
  // console.log(`Server: Token being used for Tari list files request (folder: ${folderPath}, first 10 chars): "${token.substring(0,10)}..." (Length: ${token.length})`);
  // console.log(`Server: Constructing URL: ${TARI_API_BASE_URL}?path=files&folder=${encodeURIComponent(folderPath)}`);
  // console.log(`Server: Constructed Authorization header for list files (folder: ${folderPath}): ${authorizationHeader.substring(0,20)}...`);

  try {
    const response = await fetch(`${TARI_API_BASE_URL}?path=files&folder=${encodeURIComponent(folderPath)}`, {
      method: 'GET',
      headers: {
        'Authorization': authorizationHeader,
        'Accept': 'application/json', 
      },
      cache: 'no-store',
    });
    const responseBodyText = await response.text();
    // console.log(`Server: Tari API list files raw response for folder '${folderPath}': ${responseBodyText}`);

    if (!response.ok) {
      let errorDetail = responseBodyText;
      try {
        const parsedError = JSON.parse(responseBodyText);
        if (parsedError && parsedError.error) {
          errorDetail = `${parsedError.error}${parsedError.code ? ` (Code: ${parsedError.code})` : ''}`;
        }
      } catch (e) { /* use raw text */ }
      // console.error(`Server: listTariImages - Tari API request failed: ${response.statusText} - ${errorDetail}`);
      return { success: false, error: `Tari API request failed: ${response.statusText} - ${errorDetail}` };
    }

    const result = JSON.parse(responseBodyText);
    if (result.success && Array.isArray(result.files)) {
      const imageFiles = result.files.filter((file: TariFile) =>
        file.type && file.type.startsWith('image/')
      );
      return { success: true, files: imageFiles as TariFile[] };
    } else {
      const errorMsg = result.error || result.message || "Invalid response structure from Tari API files list.";
      // console.error(`Server: listTariImages - Failed to list images: ${errorMsg}. Result: ${JSON.stringify(result)}`);
      return { success: false, error: `Failed to list images: ${errorMsg}` };
    }
  } catch (error: any) {
    // console.error(`Server: listTariImages - Error listing images from folder '${folderPath}':`, error.message, error);
    return { success: false, error: `Error listing images: ${error.message}` };
  }
}

const MAX_FILE_SIZE_GENERAL = 5 * 1024 * 1024;
const ACCEPTED_IMAGE_TYPES_GENERAL = ["image/jpeg", "image/jpg", "image/png", "image/webp", "image/gif"];

export type UploadGeneralImageFormState = { message: string; success?: boolean; errors?: { imageFile?: string[]; general?: string[]; }; fileUrl?: string; };

export async function uploadGeneralTariImage(prevState: UploadGeneralImageFormState, formData: FormData): Promise<UploadGeneralImageFormState> {
  console.log("Server: uploadGeneralTariImage action invoked.");
  try {
    // console.log("Server: uploadGeneralTariImage - Received FormData keys:", Array.from(formData.keys()));
    const imageFile = formData.get("imageFile") as File | null;

    if (!imageFile || imageFile.size === 0) {
      console.log("Server: uploadGeneralTariImage - No image file provided or file is empty.");
      return { message: "Image file is required.", errors: { imageFile: ["Please upload an image."] }, success: false };
    }
    if (imageFile.size > MAX_FILE_SIZE_GENERAL) {
      return { message: `Max file size is ${MAX_FILE_SIZE_GENERAL / (1024*1024)}MB.`, errors: { imageFile: [`Max file size is ${MAX_FILE_SIZE_GENERAL / (1024*1024)}MB.`] }, success: false };
    }
    if (!ACCEPTED_IMAGE_TYPES_GENERAL.includes(imageFile.type)) {
      return { message: "Invalid image type. Supported: JPG, PNG, GIF, WEBP.", errors: { imageFile: ["Invalid image type. Supported: JPG, PNG, GIF, WEBP."] }, success: false };
    }

    let tariImageData: { url: string; path: string };
    // console.log("Server: uploadGeneralTariImage - Attempting to upload image to Tari...");
    try {
      tariImageData = await uploadImageToTari(imageFile, TARI_GENERAL_IMAGES_FOLDER);
      // console.log("Server: uploadGeneralTariImage - Image uploaded to Tari successfully:", tariImageData);
    } catch (uploadError: any) {
      console.error("Server: uploadGeneralTariImage - Failed during uploadImageToTari call:", uploadError.message, uploadError);
      return { message: `Failed to upload image: ${uploadError.message}`, errors: { general: [uploadError.message] }, success: false };
    }

    revalidatePath('/staff-portal/dashboard/admin-images');
    return { message: "Image uploaded successfully to Tari!", success: true, fileUrl: tariImageData.url };

  } catch (error: any) {
    let plainErrorMessage = "An unexpected server error occurred during image upload.";
    if (error instanceof Error) {
      plainErrorMessage = error.message;
    } else if (typeof error === 'string') {
      plainErrorMessage = error;
    }
    console.error("Server: uploadGeneralTariImage - Full error object:", error);
    console.error("Server: uploadGeneralTariImage - Caught error message:", plainErrorMessage);

    return {
      message: `Server error: ${plainErrorMessage}`,
      success: false,
      errors: { general: [`Upload failed: ${plainErrorMessage}`] }
    };
  }
}

export type DeleteGeneralImageState = { success: boolean; message: string; };
export async function deleteGeneralTariImage(filePath: string): Promise<DeleteGeneralImageState> {
  if (!filePath) return { success: false, message: "File path is missing." };
  try {
    const deleteResult = await deleteImageFromTari(filePath);
    if (!deleteResult.success) {
      return { success: false, message: `Failed to delete image from Tari: ${deleteResult.message}` };
    }
    revalidatePath('/staff-portal/dashboard/admin-images');
    return { success: true, message: "Image deleted successfully from Tari." };
  } catch (error: any) {
    console.error("Server: deleteGeneralTariImage - Error:", error.message, error);
    return { success: false, message: `Failed to delete image: ${error.message}` };
  }
}

// --- Site Settings Actions ---
const SITE_SETTINGS_COLLECTION = "siteSettings";
const SITE_SETTINGS_DOC_ID = "global";

export async function getSiteSettings(): Promise<SiteSettings | null> {
  try {
    const docRef = doc(db, SITE_SETTINGS_COLLECTION, SITE_SETTINGS_DOC_ID);
    const docSnap = await getDoc(docRef);
    if (docSnap.exists()) {
      return docSnap.data() as SiteSettings;
    }
    return null;
  } catch (error) {
    console.error("Error fetching site settings:", error);
    return null;
  }
}

const MAX_FILE_SIZE_SITE_ASSETS = 2 * 1024 * 1024;
const ACCEPTED_IMAGE_TYPES_SITE_ASSETS = ["image/png", "image/jpeg", "image/jpg", "image/webp", "image/svg+xml", "image/x-icon", "image/vnd.microsoft.icon"];

export type UpdateSiteSettingsFormState = {
  message: string;
  success?: boolean;
  errors?: {
    logoFile?: string[];
    faviconFile?: string[];
    general?: string[];
  };
};

export async function updateSiteSettings(
  prevState: UpdateSiteSettingsFormState,
  formData: FormData
): Promise<UpdateSiteSettingsFormState> {
  // console.log("Server: updateSiteSettings action invoked.");
  try {
    const logoFile = formData.get("logoFile") as File | null;
    const faviconFile = formData.get("faviconFile") as File | null;

    // console.log("Server: updateSiteSettings - Received logoFile:", logoFile ? logoFile.name : "null");
    // console.log("Server: updateSiteSettings - Received faviconFile:", faviconFile ? faviconFile.name : "null");

    const currentSettings = (await getSiteSettings()) || {};
    let newSettings: Partial<SiteSettings> = {};
    let messages: string[] = [];

    if (logoFile && logoFile.size > 0) {
      // console.log("Server: updateSiteSettings - Processing logoFile...");
      if (logoFile.size > MAX_FILE_SIZE_SITE_ASSETS) {
        return { message: "Logo file too large.", errors: { logoFile: [`Max logo size is ${MAX_FILE_SIZE_SITE_ASSETS / (1024*1024)}MB.`] }, success: false };
      }
      if (!ACCEPTED_IMAGE_TYPES_SITE_ASSETS.includes(logoFile.type)) {
        return { message: "Invalid logo file type.", errors: { logoFile: ["Invalid logo file type."] }, success: false };
      }
      try {
        if (currentSettings.logoPathTari) {
          // console.log("Server: updateSiteSettings - Deleting old logo from Tari:", currentSettings.logoPathTari);
          await deleteImageFromTari(currentSettings.logoPathTari);
        }
        // console.log("Server: updateSiteSettings - Uploading new logo to Tari...");
        const tariLogoData = await uploadImageToTari(logoFile, `${TARI_SITE_ASSETS_FOLDER}/logo`);
        newSettings.logoUrl = tariLogoData.url;
        newSettings.logoPathTari = tariLogoData.path;
        messages.push("Logo updated.");
        // console.log("Server: updateSiteSettings - Logo updated successfully. New URL:", tariLogoData.url);
      } catch (e: any) {
        // console.error("Server: updateSiteSettings - Error updating logo:", e);
        return { message: `Logo update failed: ${e.message}`, success: false, errors: { logoFile: [e.message] } };
      }
    }

    if (faviconFile && faviconFile.size > 0) {
      // console.log("Server: updateSiteSettings - Processing faviconFile...");
      if (faviconFile.size > MAX_FILE_SIZE_SITE_ASSETS) {
        return { message: "Favicon file too large.", errors: { faviconFile: [`Max favicon size is ${MAX_FILE_SIZE_SITE_ASSETS / (1024*1024)}MB.`] }, success: false };
      }
      if (!ACCEPTED_IMAGE_TYPES_SITE_ASSETS.includes(faviconFile.type) && faviconFile.type !== 'image/vnd.microsoft.icon') {
         return { message: "Invalid favicon file type.", errors: { faviconFile: ["Invalid file type for favicon."] }, success: false };
      }
      try {
        if (currentSettings.faviconPathTari) {
          // console.log("Server: updateSiteSettings - Deleting old favicon from Tari:", currentSettings.faviconPathTari);
          await deleteImageFromTari(currentSettings.faviconPathTari);
        }
        // console.log("Server: updateSiteSettings - Uploading new favicon to Tari...");
        const tariFaviconData = await uploadImageToTari(faviconFile, `${TARI_SITE_ASSETS_FOLDER}/favicon`);
        newSettings.faviconUrl = tariFaviconData.url;
        newSettings.faviconPathTari = tariFaviconData.path;
        messages.push("Favicon updated.");
        // console.log("Server: updateSiteSettings - Favicon updated successfully. New URL:", tariFaviconData.url);
      } catch (e: any) {
        // console.error("Server: updateSiteSettings - Error updating favicon:", e);
        return { message: `Favicon update failed: ${e.message}`, success: false, errors: { faviconFile: [e.message] } };
      }
    }

    if (Object.keys(newSettings).length > 0) {
      const settingsDocRef = doc(db, SITE_SETTINGS_COLLECTION, SITE_SETTINGS_DOC_ID);
      await setDoc(settingsDocRef, { ...currentSettings, ...newSettings, updatedAt: serverTimestamp() }, { merge: true });
      revalidatePath("/staff-portal/dashboard/settings");
      revalidatePath("/"); 
      // console.log("Server: updateSiteSettings - Settings updated in Firestore. newSettings:", newSettings);
      return { message: messages.length > 0 ? messages.join(" ") : "Settings updated successfully.", success: true };
    }

    // console.log("Server: updateSiteSettings - No changes made to settings, no new files or settings updated.");
    return { message: "No new files were selected to update or no changes made.", success: true };

  } catch (error: any) {
    let plainErrorMessage = "An unexpected server error occurred updating site settings.";
    if (error instanceof Error) {
        plainErrorMessage = error.message;
    } else if (typeof error === 'string') {
        plainErrorMessage = error;
    }
    console.error("Server: updateSiteSettings - Full error object:", error);
    console.error("Server: updateSiteSettings - Caught error message:", plainErrorMessage);
    return { message: `Server error: ${plainErrorMessage}`, success: false, errors: { general: [plainErrorMessage] } };
  }
}

// --- Public Project Fetching ---
function mapDocumentToProject(docData: any, docId: string): ProjectType {
  let createdAtString: string | undefined = undefined;
  if (docData.createdAt instanceof Timestamp) {
    createdAtString = docData.createdAt.toDate().toISOString();
  } else if (docData.createdAt && typeof docData.createdAt.seconds === 'number') {
    createdAtString = new Timestamp(docData.createdAt.seconds, docData.createdAt.nanoseconds || 0).toDate().toISOString();
  }

  return {
    id: docId,
    title: docData.title || "Untitled Project",
    organization: docData.organization || "N/A",
    description: docData.description || "No description available.",
    imageUrl: docData.imageUrl || "", 
    imageHint: docData.imageHint || "project image",
    impact: Array.isArray(docData.impact) ? docData.impact.filter((item: any): item is string => typeof item === 'string') : [],
    createdAt: createdAtString,
    imagePathTari: docData.imagePathTari || undefined,
  };
}

export async function getPublicProjects(count?: number): Promise<ProjectType[]> {
  try {
    const projectsCol = collection(db, 'projects');
    let q = query(projectsCol, orderBy('createdAt', 'desc'));
    if (count) {
      q = query(projectsCol, orderBy('createdAt', 'desc'), limit(count));
    }
    const projectSnapshot = await getDocs(q);
    return projectSnapshot.docs.map(doc => mapDocumentToProject(doc.data(), doc.id));
  } catch (error) {
    console.error("Error fetching public projects:", error);
    return [];
  }
}

export async function getPublicProjectById(id: string): Promise<ProjectType | null> {
  try {
    const projectRef = doc(db, "projects", id);
    const projectSnap = await getDoc(projectRef);
    if (projectSnap.exists()) {
      return mapDocumentToProject(projectSnap.data(), projectSnap.id);
    }
    return null;
  } catch (error) {
    console.error(`Error fetching public project by ID ${id}:`, error);
    return null;
  }
}

// --- Seed Initial Projects ---
export type SeedProjectsState = {
  message: string;
  success: boolean;
  addedCount?: number;
  skippedCount?: number;
  errors?: string[];
};

export async function seedInitialProjects(): Promise<SeedProjectsState> {
  try {
    const projectsRef = collection(db, "projects");
    const defaultImageUrl = "https://files.tari.africa/api.php?path=public&name=1748413232_6836ab30547e7.png";
    let addedCount = 0;
    let skippedCount = 0;
    const errors: string[] = [];

    const batch = writeBatch(db);

    for (const seedProject of KEY_PROJECTS_SEED_DATA) {
      const q = query(projectsRef, where("title", "==", seedProject.title));
      const existingDocs = await getDocs(q);

      if (existingDocs.empty) {
        const newProjectRef = doc(projectsRef); 
        batch.set(newProjectRef, {
          title: seedProject.title,
          organization: seedProject.organization,
          description: seedProject.description,
          imageUrl: defaultImageUrl,
          imagePathTari: null, 
          imageHint: seedProject.imageHint,
          impact: seedProject.impact,
          createdAt: serverTimestamp(),
        });
        addedCount++;
      } else {
        skippedCount++;
        // console.log(`Skipping project "${seedProject.title}" as it (or one with the same title) likely already exists.`);
      }
    }

    if (addedCount > 0) {
      await batch.commit();
    }

    revalidatePath('/staff-portal/dashboard/admin-projects');
    revalidatePath('/projects');
    revalidatePath('/');

    let message = "";
    if (addedCount > 0) message += `${addedCount} project(s) seeded successfully. `;
    if (skippedCount > 0) message += `${skippedCount} project(s) skipped (likely duplicates by title).`;
    if (addedCount === 0 && skippedCount === 0) message = "No new projects to seed from static data.";
    
    return {
      message: message.trim(),
      success: true,
      addedCount,
      skippedCount,
      errors: errors.length > 0 ? errors : undefined,
    };

  } catch (error: any) {
    console.error("Error seeding projects:", error);
    return {
      message: `Error seeding projects: ${error.message}`,
      success: false,
      errors: [error.message],
    };
  }
}
