// Posts table CRUD operations (using existing posts table)
// Manages blog posts with SEO

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

export interface Post {
    id: string;
    site_id: string;
    title: string;
    slug: string;
    content: string | null;
    excerpt: string | null;
    status: string;
    published_at: Date | null;
    meta_title: string | null;
    meta_description: string | null;
    created_at: Date;
    updated_at: Date;
}

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

    let sql = 'SELECT * FROM posts 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('title', 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<Post>(sql, params);

    // Get total count
    const countSql = 'SELECT COUNT(*) FROM posts 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 post by ID
 */
export async function getPostById(id: string): Promise<Post | null> {
    if (!isValidUUID(id)) {
        throw new Error('Invalid post ID format');
    }

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

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

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

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

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

    let sql = 'SELECT * FROM posts 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<Post>(sql, params);
    return rows;
}

/**
 * Create new post (simplified - no SEO requirement)
 */
export async function createPost(data: {
    site_id: string;
    title: string;
    slug: string;
    content: string;
    excerpt?: string;
    meta_title?: string;
    meta_description?: string;
    status?: string;
}): Promise<Post> {
    const { rows } = await pool.query<Post>(
        `INSERT INTO posts (site_id, title, slug, content, excerpt, meta_title, meta_description, status)
     VALUES ($1, $2, $3, $4, $5, $6, $7, $8)
     RETURNING *`,
        [
            data.site_id,
            data.title,
            data.slug,
            data.content,
            data.excerpt || '',
            data.meta_title || data.title,
            data.meta_description || '',
            data.status || 'draft'
        ]
    );

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

    return rows[0];
}

/**
 * Update existing post
 */
export async function updatePost(id: string, data: Partial<Post>): Promise<Post> {
    if (!isValidUUID(id)) {
        throw new Error('Invalid post ID format');
    }

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

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

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

    return rows[0];
}

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

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

/**
 * Publish post
 */
export async function publishPost(id: string): Promise<Post> {
    return updatePost(id, {
        status: 'published',
        published_at: new Date()
    });
}

/**
 * Get posts count by status
 */
export async function getPostsCountByStatus(siteId?: string): Promise<Record<string, number>> {
    const sql = siteId
        ? 'SELECT status, COUNT(*) as count FROM posts WHERE site_id = $1 GROUP BY status'
        : 'SELECT status, COUNT(*) as count FROM posts 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>);
}
