// EN: Unit tests for @goodgo/types — validate type shapes and exported constants.
// VI: Unit tests cho @goodgo/types — kiểm tra hình dạng type và các hằng số xuất.
import { describe, it, expect } from 'vitest';
import type {
  ApiResponse,
  ApiError,
  PaginatedResponse,
  PaginationQuery,
  LoginDto,
  RegisterDto,
  AuthResponse,
  RefreshTokenDto,
  TokenPayload,
  ChangePasswordDto,
  ForgotPasswordDto,
  ResetPasswordDto,
  User,
  UserResponse,
  CreateUserDto,
  UpdateUserDto,
} from './index';
import { Role } from './index';

// ---------------------------------------------------------------------------
// Role enum
// ---------------------------------------------------------------------------
describe('Role enum', () => {
  it('should define USER, ADMIN, SUPER_ADMIN values', () => {
    expect(Role.USER).toBe('USER');
    expect(Role.ADMIN).toBe('ADMIN');
    expect(Role.SUPER_ADMIN).toBe('SUPER_ADMIN');
  });

  it('should have exactly 3 members', () => {
    const values = Object.values(Role);
    expect(values).toHaveLength(3);
  });
});

// ---------------------------------------------------------------------------
// ApiResponse shape
// ---------------------------------------------------------------------------
describe('ApiResponse type shape', () => {
  it('success response should satisfy interface contract', () => {
    const response: ApiResponse<number> = {
      success: true,
      data: 42,
      message: 'OK',
      timestamp: new Date().toISOString(),
    };
    expect(response.success).toBe(true);
    expect(response.data).toBe(42);
    expect(response.timestamp).toBeTruthy();
  });

  it('error response should satisfy interface contract', () => {
    const error: ApiError = {
      code: 'NOT_FOUND',
      message: 'Resource not found / Không tìm thấy tài nguyên',
    };
    const response: ApiResponse<null> = {
      success: false,
      error,
      timestamp: new Date().toISOString(),
    };
    expect(response.success).toBe(false);
    expect(response.error?.code).toBe('NOT_FOUND');
  });

  it('ApiError with details should store extra info', () => {
    const error: ApiError = {
      code: 'VALIDATION_ERROR',
      message: 'Invalid input / Dữ liệu không hợp lệ',
      details: { field: 'email', reason: 'format' },
    };
    expect(error.details?.field).toBe('email');
  });
});

// ---------------------------------------------------------------------------
// PaginatedResponse shape
// ---------------------------------------------------------------------------
describe('PaginatedResponse type shape', () => {
  it('should carry items array and pagination metadata', () => {
    const paged: PaginatedResponse<string> = {
      success: true,
      data: ['a', 'b'],
      timestamp: new Date().toISOString(),
      pagination: { page: 1, limit: 10, total: 2, totalPages: 1 },
    };
    expect(paged.data).toHaveLength(2);
    expect(paged.pagination.totalPages).toBe(1);
  });
});

// ---------------------------------------------------------------------------
// PaginationQuery shape
// ---------------------------------------------------------------------------
describe('PaginationQuery type shape', () => {
  it('should allow partial query parameters', () => {
    const q1: PaginationQuery = {};
    const q2: PaginationQuery = { page: 2, limit: 20 };
    const q3: PaginationQuery = { sortBy: 'createdAt', sortOrder: 'desc' };
    expect(q1).toEqual({});
    expect(q2.limit).toBe(20);
    expect(q3.sortOrder).toBe('desc');
  });
});

// ---------------------------------------------------------------------------
// Auth DTOs
// ---------------------------------------------------------------------------
describe('Auth DTO type shapes', () => {
  it('LoginDto requires email and password', () => {
    const dto: LoginDto = { email: 'test@goodgo.vn', password: 'Secret123!' };
    expect(dto.email).toContain('@');
  });

  it('RegisterDto includes confirmPassword', () => {
    const dto: RegisterDto = {
      email: 'new@goodgo.vn',
      password: 'Secret123!',
      confirmPassword: 'Secret123!',
    };
    expect(dto.password).toBe(dto.confirmPassword);
  });

  it('RefreshTokenDto wraps a single token string', () => {
    const dto: RefreshTokenDto = { refreshToken: 'rt_abc123' };
    expect(dto.refreshToken).toBeTruthy();
  });

  it('ChangePasswordDto has currentPassword and newPassword', () => {
    const dto: ChangePasswordDto = { currentPassword: 'Old1!', newPassword: 'New1!' };
    expect(dto.newPassword).not.toBe(dto.currentPassword);
  });

  it('ForgotPasswordDto has email', () => {
    const dto: ForgotPasswordDto = { email: 'user@goodgo.vn' };
    expect(dto.email).toBeTruthy();
  });

  it('ResetPasswordDto has token and newPassword', () => {
    const dto: ResetPasswordDto = { token: 'reset_tok', newPassword: 'New1!' };
    expect(dto.token).toBeTruthy();
  });

  it('TokenPayload has required fields', () => {
    const payload: TokenPayload = {
      userId: 'user-123',
      email: 'user@goodgo.vn',
      role: 'owner',
    };
    expect(payload.userId).toBeTruthy();
  });
});

// ---------------------------------------------------------------------------
// User DTOs
// ---------------------------------------------------------------------------
describe('User type shapes', () => {
  it('User entity includes all required fields', () => {
    const user: User = {
      id: 'u-1',
      email: 'owner@goodgo.vn',
      role: Role.ADMIN,
      isActive: true,
      createdAt: new Date(),
      updatedAt: new Date(),
    };
    expect(user.role).toBe(Role.ADMIN);
    expect(user.isActive).toBe(true);
  });

  it('UserResponse uses string timestamps', () => {
    const resp: UserResponse = {
      id: 'u-2',
      email: 'staff@goodgo.vn',
      role: Role.USER,
      isActive: true,
      createdAt: '2026-01-01T00:00:00Z',
      updatedAt: '2026-01-01T00:00:00Z',
    };
    expect(typeof resp.createdAt).toBe('string');
  });

  it('CreateUserDto allows optional role', () => {
    const dto1: CreateUserDto = { email: 'a@b.com', password: 'P@ss1' };
    const dto2: CreateUserDto = { email: 'a@b.com', password: 'P@ss1', role: Role.ADMIN };
    expect(dto1.role).toBeUndefined();
    expect(dto2.role).toBe(Role.ADMIN);
  });

  it('UpdateUserDto is fully optional', () => {
    const dto: UpdateUserDto = {};
    expect(dto.email).toBeUndefined();
    expect(dto.role).toBeUndefined();
    expect(dto.isActive).toBeUndefined();
  });

  it('AuthResponse carries accessToken, refreshToken and user', () => {
    const resp: AuthResponse = {
      accessToken: 'at_xyz',
      refreshToken: 'rt_xyz',
      user: {
        id: 'u-3',
        email: 'merchant@goodgo.vn',
        role: Role.USER,
        isActive: true,
        createdAt: '2026-01-01T00:00:00Z',
        updatedAt: '2026-01-01T00:00:00Z',
      },
    };
    expect(resp.accessToken).toBeTruthy();
    expect(resp.user.email).toBe('merchant@goodgo.vn');
  });
});
