// Pages table CRUD operations
// Manages static landing pages with routes

import { pool } from '@/lib/db';
import type { FilterOptions, PaginationResult } from './types';
import { buildWhere, buildSearch, buildPagination, buildUpdateSet, getSingleResult, isValidUUID } from './utils';

export interface Page {
    id: string;
    site_id: string;
    name: string;
    route: string;
    html_content: string | null;
    meta_title: string | null;
    meta_description: string | null;
    status: string;
    published_at: Date | null;
    created_at: Date;
    updated_at: Date;
}

/**
 * Get all pages with filtering and pagination
 */
export async function getPages(options: FilterOptions = {}): Promise<PaginationResult<Page>> {
    const { limit = 50, offset = 0, status, search, siteId } = options;

    let sql = 'SELECT * FROM pages WHERE 1=1';
    const params: any[] = [];
    let paramIndex = 1;

    if (status) {
        sql += ` AND status = $${paramIndex++}`;
        params.push(status);
    }

    if (siteId) {
        sql += ` AND site_id = $${paramIndex++}`;
        params.push(siteId);
    }

    if (search) {
        const [searchSql, searchParam] = buildSearch('name', search, paramIndex++);
        sql += searchSql;
        params.push(searchParam);
    }

    const [paginationSql, safeLimit, safeOffset] = buildPagination(limit, offset, paramIndex);
    sql += ' ORDER BY created_at DESC' + paginationSql;
    params.push(safeLimit, safeOffset);

    const { rows } = await pool.query<Page>(sql, params);

    // Get total count
    const countSql = 'SELECT COUNT(*) FROM pages WHERE 1=1' +
        (status ? ` AND status = $1` : '') +
        (siteId ? ` AND site_id = $${status ? 2 : 1}` : '');
    const countParams = [status, siteId].filter(Boolean);
    const { rows: countRows } = await pool.query<{ count: string }>(countSql, countParams);
    const total = parseInt(countRows[0]?.count || '0');

    return {
        data: rows,
        total,
        limit: safeLimit,
        offset: safeOffset,
        hasMore: safeOffset + rows.length < total
    };
}

/**
 * Get single page by ID
 */
export async function getPageById(id: string): Promise<Page | null> {
    if (!isValidUUID(id)) {
        throw new Error('Invalid page ID format');
    }

    const { rows } = await pool.query<Page>(
        'SELECT * FROM pages WHERE id = $1',
        [id]
    );
    return getSingleResult(rows);
}

/**
 * Get page by site and route
 */
export async function getPageByRoute(siteId: string, route: string): Promise<Page | null> {
    if (!isValidUUID(siteId)) {
        throw new Error('Invalid site ID format');
    }

    const { rows } = await pool.query<Page>(
        'SELECT * FROM pages WHERE site_id = $1 AND route = $2',
        [siteId, route]
    );
    return getSingleResult(rows);
}

/**
 * Get pages by site
 */
export async function getPagesBySite(siteId: string, options: FilterOptions = {}): Promise<Page[]> {
    if (!isValidUUID(siteId)) {
        throw new Error('Invalid site ID format');
    }

    const { limit = 50, offset = 0, status } = options;

    let sql = 'SELECT * FROM pages WHERE site_id = $1';
    const params: any[] = [siteId];
    let paramIndex = 2;

    if (status) {
        sql += ` AND status = $${paramIndex++}`;
        params.push(status);
    }

    const [paginationSql, safeLimit, safeOffset] = buildPagination(limit, offset, paramIndex);
    sql += ' ORDER BY created_at DESC' + paginationSql;
    params.push(safeLimit, safeOffset);

    const { rows } = await pool.query<Page>(sql, params);
    return rows;
}

/**
 * Create new page with validation
 */
export async function createPage(data: unknown): Promise<Page> {
    // Import Zod schema
    const { PageSchema, validateForCreate } = await import('./schemas');

    // Validate input
    const validatedData = validateForCreate(PageSchema, data, 'Page');

    const { rows } = await pool.query<Page>(
        `INSERT INTO pages (site_id, name, route, html_content, meta_title, meta_description, status)
     VALUES ($1, $2, $3, $4, $5, $6, $7)
     RETURNING *`,
        [
            validatedData.site_id,
            validatedData.name,
            validatedData.route,
            validatedData.html_content || '',
            validatedData.meta_title || '',
            validatedData.meta_description || '',
            validatedData.status || 'draft'
        ]
    );

    if (rows.length === 0) {
        throw new Error('Failed to create page');
    }

    return rows[0];
}

/**
 * Update existing page
 */
export async function updatePage(id: string, data: unknown): Promise<Page> {
    if (!isValidUUID(id)) {
        throw new Error('Invalid page ID format');
    }

    const { PartialPageSchema, validateForUpdate } = await import('./schemas');

    const validatedData = validateForUpdate(
        PartialPageSchema,
        { ...(data as Record<string, any>), id },
        'Page'
    );

    const [setClause, values] = buildUpdateSet(validatedData);
    values.push(id);

    const { rows } = await pool.query<Page>(
        `UPDATE pages SET ${setClause}, updated_at = NOW()
     WHERE id = $${values.length}
     RETURNING *`,
        values
    );

    if (rows.length === 0) {
        throw new Error('Page not found');
    }

    return rows[0];
}

/**
 * Delete page
 */
export async function deletePage(id: string): Promise<boolean> {
    if (!isValidUUID(id)) {
        throw new Error('Invalid page ID format');
    }

    const result = await pool.query('DELETE FROM pages WHERE id = $1', [id]);
    return result.rowCount ? result.rowCount > 0 : false;
}

/**
 * Publish page
 */
export async function publishPage(id: string): Promise<Page> {
    return updatePage(id, {
        status: 'published',
        published_at: new Date()
    });
}

/**
 * Get pages count by status
 */
export async function getPagesCountByStatus(siteId?: string): Promise<Record<string, number>> {
    const sql = siteId
        ? 'SELECT status, COUNT(*) as count FROM pages WHERE site_id = $1 GROUP BY status'
        : 'SELECT status, COUNT(*) as count FROM pages GROUP BY status';

    const params = siteId ? [siteId] : [];
    const { rows } = await pool.query<{ status: string; count: string }>(sql, params);

    return rows.reduce((acc, row) => {
        acc[row.status] = parseInt(row.count);
        return acc;
    }, {} as Record<string, number>);
}
