/**
 * Auth Context Tests
 * Tests for the authentication context and has_voted state fix
 */

import React from "react"
import { render, screen, waitFor } from "@testing-library/react"
import { AuthProvider, useAuth } from "@/lib/auth-context"
import * as api from "@/lib/api"

// Mock the API module
jest.mock("@/lib/api", () => ({
  authApi: {
    login: jest.fn(),
    register: jest.fn(),
    getProfile: jest.fn(),
    logout: jest.fn(),
  },
  getAuthToken: jest.fn(),
  setAuthToken: jest.fn(),
  clearAuthToken: jest.fn(),
}))

// Mock window.localStorage
const localStorageMock = {
  getItem: jest.fn(),
  setItem: jest.fn(),
  removeItem: jest.fn(),
  clear: jest.fn(),
}
global.localStorage = localStorageMock as any

describe("Auth Context - Bug #2: has_voted State Fix", () => {
  beforeEach(() => {
    jest.clearAllMocks()
    localStorageMock.getItem.mockReturnValue(null)
  })

  test("login response includes has_voted field", async () => {
    const mockLoginResponse = {
      data: {
        access_token: "test-token",
        id: 1,
        email: "test@example.com",
        first_name: "Test",
        last_name: "User",
        has_voted: false,
        expires_in: 1800,
      },
      status: 200,
    }

    ;(api.authApi.login as jest.Mock).mockResolvedValue(mockLoginResponse)
    ;(api.setAuthToken as jest.Mock).mockImplementation(() => {})

    let authContextValue: any

    const TestComponent = () => {
      authContextValue = useAuth()
      return <div>{authContextValue.isLoading ? "Loading..." : "Ready"}</div>
    }

    const { rerender } = render(
      <AuthProvider>
        <TestComponent />
      </AuthProvider>
    )

    // Simulate login
    await waitFor(async () => {
      await authContextValue.login("test@example.com", "password123")
    })

    expect(authContextValue.user).toBeDefined()
    expect(authContextValue.user?.has_voted).toBeDefined()
    expect(typeof authContextValue.user?.has_voted).toBe("boolean")
  })

  test("register response includes has_voted field", async () => {
    const mockRegisterResponse = {
      data: {
        access_token: "test-token",
        id: 2,
        email: "newuser@example.com",
        first_name: "New",
        last_name: "User",
        has_voted: false,
        expires_in: 1800,
      },
      status: 200,
    }

    ;(api.authApi.register as jest.Mock).mockResolvedValue(mockRegisterResponse)
    ;(api.setAuthToken as jest.Mock).mockImplementation(() => {})

    let authContextValue: any

    const TestComponent = () => {
      authContextValue = useAuth()
      return <div>{authContextValue.isLoading ? "Loading..." : "Ready"}</div>
    }

    render(
      <AuthProvider>
        <TestComponent />
      </AuthProvider>
    )

    // Simulate registration
    await waitFor(async () => {
      await authContextValue.register(
        "newuser@example.com",
        "password123",
        "New",
        "User",
        "ID123456"
      )
    })

    expect(authContextValue.user?.has_voted).toBe(false)
  })

  test("has_voted is correctly set from server response, not hardcoded", async () => {
    const mockLoginResponseVoted = {
      data: {
        access_token: "test-token",
        id: 3,
        email: "voted@example.com",
        first_name: "Voted",
        last_name: "User",
        has_voted: true, // User has already voted
        expires_in: 1800,
      },
      status: 200,
    }

    ;(api.authApi.login as jest.Mock).mockResolvedValue(mockLoginResponseVoted)
    ;(api.setAuthToken as jest.Mock).mockImplementation(() => {})

    let authContextValue: any

    const TestComponent = () => {
      authContextValue = useAuth()
      return <div>{authContextValue.isLoading ? "Loading..." : "Ready"}</div>
    }

    render(
      <AuthProvider>
        <TestComponent />
      </AuthProvider>
    )

    // Simulate login with user who has voted
    await waitFor(async () => {
      await authContextValue.login("voted@example.com", "password123")
    })

    // Verify has_voted is true (from server) not false (hardcoded)
    expect(authContextValue.user?.has_voted).toBe(true)
  })

  test("has_voted defaults to false if not in response", async () => {
    const mockLoginResponseNoField = {
      data: {
        access_token: "test-token",
        id: 4,
        email: "nofield@example.com",
        first_name: "No",
        last_name: "Field",
        // has_voted missing from response
        expires_in: 1800,
      },
      status: 200,
    }

    ;(api.authApi.login as jest.Mock).mockResolvedValue(mockLoginResponseNoField)
    ;(api.setAuthToken as jest.Mock).mockImplementation(() => {})

    let authContextValue: any

    const TestComponent = () => {
      authContextValue = useAuth()
      return <div>{authContextValue.isLoading ? "Loading..." : "Ready"}</div>
    }

    render(
      <AuthProvider>
        <TestComponent />
      </AuthProvider>
    )

    await waitFor(async () => {
      await authContextValue.login("nofield@example.com", "password123")
    })

    // Should default to false if not present
    expect(authContextValue.user?.has_voted).toBe(false)
  })

  test("profile refresh updates has_voted state", async () => {
    const mockProfileResponse = {
      data: {
        id: 5,
        email: "profile@example.com",
        first_name: "Profile",
        last_name: "User",
        has_voted: true,
        created_at: new Date().toISOString(),
      },
      status: 200,
    }

    ;(api.authApi.getProfile as jest.Mock).mockResolvedValue(mockProfileResponse)
    ;(api.getAuthToken as jest.Mock).mockReturnValue("test-token")

    let authContextValue: any

    const TestComponent = () => {
      authContextValue = useAuth()
      return (
        <div>
          {authContextValue.user?.has_voted !== undefined
            ? `has_voted: ${authContextValue.user.has_voted}`
            : "no user"}
        </div>
      )
    }

    render(
      <AuthProvider>
        <TestComponent />
      </AuthProvider>
    )

    // Simulate profile refresh
    await waitFor(async () => {
      await authContextValue.refreshProfile()
    })

    expect(authContextValue.user?.has_voted).toBe(true)
  })
})

describe("Auth Context - API Token Type Fix", () => {
  test("AuthToken interface includes has_voted field", () => {
    // This test ensures the TypeScript interface is correct
    const token: api.AuthToken = {
      access_token: "token",
      expires_in: 1800,
      id: 1,
      email: "test@example.com",
      first_name: "Test",
      last_name: "User",
      has_voted: false,
    }

    expect(token.has_voted).toBeDefined()
    expect(typeof token.has_voted).toBe("boolean")
  })
})
