import { User, type IUserRepository } from '@crafted/domain';
import { db } from '@crafted/database';

export class PrismaUserRepository implements IUserRepository {
  async findById(id: string): Promise<User | null> {
    const data = await db.user.findUnique({
      where: { id },
    });

    if (!data) return null;

    const userResult = User.create({
      id: data.id,
      email: data.email,
      name: data.name ?? undefined,
      supabaseId: data.supabaseId!,
      stripeCustomerId: data.stripeCustomerId ?? undefined,
      createdAt: data.createdAt,
      updatedAt: data.updatedAt,
    });

    return userResult.isSuccess() ? userResult.getValue() : null;
  }

  async findByEmail(email: string): Promise<User | null> {
    const data = await db.user.findUnique({
      where: { email },
    });

    if (!data) return null;

    const userResult = User.create({
      id: data.id,
      email: data.email,
      name: data.name ?? undefined,
      supabaseId: data.supabaseId!,
      stripeCustomerId: data.stripeCustomerId ?? undefined,
      createdAt: data.createdAt,
      updatedAt: data.updatedAt,
    });

    return userResult.isSuccess() ? userResult.getValue() : null;
  }

  async findBySupabaseId(supabaseId: string): Promise<User | null> {
    const data = await db.user.findUnique({
      where: { supabaseId },
    });

    if (!data) return null;

    const userResult = User.create({
      id: data.id,
      email: data.email,
      name: data.name ?? undefined,
      supabaseId: data.supabaseId!,
      stripeCustomerId: data.stripeCustomerId ?? undefined,
      createdAt: data.createdAt,
      updatedAt: data.updatedAt,
    });

    return userResult.isSuccess() ? userResult.getValue() : null;
  }

  async findByStripeCustomerId(customerId: string): Promise<User | null> {
    const data = await db.user.findUnique({
      where: { stripeCustomerId: customerId },
    });

    if (!data) return null;

    const userResult = User.create({
      id: data.id,
      email: data.email,
      name: data.name ?? undefined,
      supabaseId: data.supabaseId!,
      stripeCustomerId: data.stripeCustomerId ?? undefined,
      createdAt: data.createdAt,
      updatedAt: data.updatedAt,
    });

    return userResult.isSuccess() ? userResult.getValue() : null;
  }

  async save(user: User): Promise<void> {
    const plain = user.toPlainObject();

    await db.user.upsert({
      where: { id: plain.id },
      create: {
        id: plain.id,
        email: plain.email,
        name: plain.name,
        supabaseId: plain.supabaseId,
        stripeCustomerId: plain.stripeCustomerId,
      },
      update: {
        email: plain.email,
        name: plain.name,
        stripeCustomerId: plain.stripeCustomerId,
        updatedAt: plain.updatedAt,
      },
    });
  }

  async delete(id: string): Promise<void> {
    await db.user.delete({
      where: { id },
    });
  }
}
