import { describe, it, expect } from 'vitest'
import {
  createNote,
  updateNote,
  uploadAttachment,
  deleteAttachment,
  saveAttachmentAnnotations,
  saveNotePdf,
} from '../actions'

const VALID_UUID = '11111111-1111-4111-8111-111111111111'

/**
 * Covers the input-validation guards that run before any DB/auth access.
 * The happy path (insert/update + RLS) is verified via gstack-smoke +
 * Vercel-Preview, not unit-mocked.
 */

describe('createNote input validation', () => {
  it('rejects a missing/invalid project id before touching the DB', async () => {
    // @ts-expect-error — deliberately omitting projectId
    const res = await createNote({ title: 'x', canvasData: null })
    expect(res).toEqual({ ok: false, error: 'invalid input' })
  })

  it('rejects a non-uuid project id', async () => {
    const res = await createNote({ projectId: 'not-a-uuid', canvasData: null })
    expect(res).toEqual({ ok: false, error: 'invalid input' })
  })

  it('accepts a seeded non-v4 demo uuid (regression: G61-KDK-DEMO save bug)', async () => {
    // The demo project id is not RFC-4122 v4. It must pass input validation and
    // only fail later at auth/DB (which, in this unit env, means createClient
    // throws because there's no request scope — that throw IS the proof that
    // validation passed). The one thing that must NOT happen is 'invalid input'.
    try {
      const res = await createNote({
        projectId: '11111111-1111-1111-1111-1111111111aa',
        title: 'x',
        canvasData: { version: 1, strokes: [] },
      })
      if (!res.ok) expect(res.error).not.toBe('invalid input')
    } catch {
      // createClient threw → validation already passed. Pass.
    }
  })
})

describe('updateNote input validation', () => {
  it('rejects a non-uuid note id', async () => {
    const res = await updateNote('nope', {
      projectId: '11111111-1111-1111-1111-111111111111',
      canvasData: null,
    })
    expect(res).toEqual({ ok: false, error: 'invalid id' })
  })

  it('rejects invalid input even when the id is valid', async () => {
    const res = await updateNote('11111111-1111-4111-8111-111111111111', {
      // @ts-expect-error — deliberately invalid projectId
      projectId: 123,
      canvasData: null,
    })
    expect(res).toEqual({ ok: false, error: 'invalid input' })
  })
})

describe('attachment action guards', () => {
  it('uploadAttachment rejects a non-uuid note id', async () => {
    const res = await uploadAttachment('nope', new FormData())
    expect(res).toEqual({ ok: false, error: 'invalid id' })
  })

  it('uploadAttachment rejects a request without a file', async () => {
    const res = await uploadAttachment(VALID_UUID, new FormData())
    expect(res).toEqual({ ok: false, error: 'no file' })
  })

  it('deleteAttachment rejects a non-uuid id', async () => {
    expect(await deleteAttachment('nope')).toEqual({ ok: false, error: 'invalid id' })
  })

  it('saveAttachmentAnnotations rejects a non-uuid id', async () => {
    expect(await saveAttachmentAnnotations('nope', null)).toEqual({ ok: false, error: 'invalid id' })
  })
})

describe('saveNotePdf guards', () => {
  it('rejects a non-uuid note id', async () => {
    expect(await saveNotePdf('nope', VALID_UUID, 'AAAA', 'x')).toEqual({
      ok: false,
      error: 'invalid id',
    })
  })

  it('rejects a non-uuid project id', async () => {
    expect(await saveNotePdf(VALID_UUID, 'nope', 'AAAA', 'x')).toEqual({
      ok: false,
      error: 'invalid id',
    })
  })

  it('rejects an empty pdf payload', async () => {
    expect(await saveNotePdf(VALID_UUID, VALID_UUID, '', 'x')).toEqual({
      ok: false,
      error: 'no pdf',
    })
  })
})
