import { ApiError, request, type Page } from './client';

export type ReadProgress = {
    user_id: string;
    manga_id: string;
    chapter_id: string | null;
    page: number;
    updated_at: string;
};

export type ReadProgressSummary = {
    manga_id: string;
    manga_title: string;
    manga_cover_image_path: string | null;
    chapter_id: string | null;
    /** `null` if the chapter was deleted after the progress was written. */
    chapter_number: number | null;
    /** Page count of the last-read chapter (`null` when unknown / deleted).
     * Lets the shelf tell a finished series from one still in progress. */
    chapter_page_count: number | null;
    page: number;
    updated_at: string;
    /** Chapters past the reader's last-read chapter — a personal "new
     * since you last read" count. `0` when caught up or when the position
     * is unknown (manga-level progress / deleted chapter). */
    new_chapters_count: number;
};

export type ReadProgressPage = {
    items: ReadProgressSummary[];
    page: Page;
};

export type UpsertReadProgress = {
    manga_id: string;
    chapter_id?: string | null;
    page?: number | null;
};

export async function updateReadProgress(
    input: UpsertReadProgress
): Promise<ReadProgress> {
    return request<ReadProgress>('/v1/me/read-progress', {
        method: 'PUT',
        headers: { 'content-type': 'application/json' },
        body: JSON.stringify(input)
    });
}

export async function listMyReadProgress(
    opts: { limit?: number; offset?: number } = {}
): Promise<ReadProgressPage> {
    const params = new URLSearchParams();
    if (opts.limit != null) params.set('limit', String(opts.limit));
    if (opts.offset != null) params.set('offset', String(opts.offset));
    const qs = params.toString();
    return request<ReadProgressPage>(
        `/v1/me/read-progress${qs ? `?${qs}` : ''}`
    );
}

export async function listMyReadProgressOrEmpty(): Promise<ReadProgressPage> {
    try {
        return await listMyReadProgress();
    } catch (e) {
        if (e instanceof ApiError && e.status === 401) {
            return { items: [], page: { limit: 50, offset: 0, total: null } };
        }
        throw e;
    }
}

/**
 * Single-manga response shape returned by GET /me/read-progress/:id.
 * Includes `chapter_number` so the "Continue reading" CTA can render
 * without resolving the chapter id against a paged chapters list.
 */
export type ReadProgressForManga = {
    manga_id: string;
    chapter_id: string | null;
    /** `null` if the chapter was deleted after the progress was written. */
    chapter_number: number | null;
    page: number;
    updated_at: string;
    /** Distinct chapter numbers past the last-read chapter — the
     * authoritative "new since last read" count (over all chapters, not the
     * detail page's paginated list). `0` when caught up / position unknown. */
    new_chapters_count: number;
};

/**
 * Returns the user's progress for a specific manga, or `null` when
 * they've never opened it (or aren't signed in). Used by the manga
 * detail page's "Continue from Ch. N" CTA and by the reader to seed
 * its session-local high-water mark from the persisted value.
 */
export async function getMyReadProgressForManga(
    mangaId: string
): Promise<ReadProgressForManga | null> {
    try {
        return await request<ReadProgressForManga>(
            `/v1/me/read-progress/${encodeURIComponent(mangaId)}`
        );
    } catch (e) {
        if (e instanceof ApiError && (e.status === 404 || e.status === 401)) {
            return null;
        }
        throw e;
    }
}

export async function clearReadProgress(mangaId: string): Promise<void> {
    await request<void>(
        `/v1/me/read-progress/${encodeURIComponent(mangaId)}`,
        { method: 'DELETE' }
    );
}
