/**
 * User Database Service
 * CRUD operations for users
 */

import prisma from './prisma';
import type { User, UserType, Prisma } from '@prisma/client';
import type { PaginationOptions, PaginatedResult } from './types';
import { createPaginatedResult } from './types';

// Create a new user
export async function createUser(data: {
  email: string;
  name: string;
  walletAddress?: string;
  passwordHash?: string;
  avatarUrl?: string;
  bio?: string;
  latitude?: number;
  longitude?: number;
  address?: string;
  city?: string;
  country?: string;
  userType?: UserType;
}): Promise<User> {
  return prisma.user.create({
    data: {
      ...data,
      userType: data.userType || 'CONSUMER',
    },
  });
}

// Get user by ID
export async function getUserById(id: string): Promise<User | null> {
  return prisma.user.findUnique({
    where: { id },
  });
}

// Get user by email
export async function getUserByEmail(email: string): Promise<User | null> {
  return prisma.user.findUnique({
    where: { email },
  });
}

// Get user by wallet address
export async function getUserByWalletAddress(walletAddress: string): Promise<User | null> {
  return prisma.user.findUnique({
    where: { walletAddress },
  });
}

// Update user
export async function updateUser(
  id: string,
  data: Prisma.UserUpdateInput
): Promise<User> {
  return prisma.user.update({
    where: { id },
    data,
  });
}

// Delete user
export async function deleteUser(id: string): Promise<User> {
  return prisma.user.delete({
    where: { id },
  });
}

// Get all users with pagination
export async function getUsers(
  options: PaginationOptions = {},
  filters?: {
    userType?: UserType;
    city?: string;
    country?: string;
  }
): Promise<PaginatedResult<User>> {
  const page = options.page || 1;
  const limit = options.limit || 20;
  const skip = (page - 1) * limit;

  const where: Prisma.UserWhereInput = {};
  if (filters?.userType) where.userType = filters.userType;
  if (filters?.city) where.city = { contains: filters.city, mode: 'insensitive' };
  if (filters?.country) where.country = { contains: filters.country, mode: 'insensitive' };

  const [users, total] = await Promise.all([
    prisma.user.findMany({
      where,
      skip,
      take: limit,
      orderBy: { createdAt: 'desc' },
    }),
    prisma.user.count({ where }),
  ]);

  return createPaginatedResult(users, total, page, limit);
}

// Get users by type
export async function getUsersByType(userType: UserType): Promise<User[]> {
  return prisma.user.findMany({
    where: { userType },
    orderBy: { name: 'asc' },
  });
}

// Update last login
export async function updateLastLogin(id: string): Promise<User> {
  return prisma.user.update({
    where: { id },
    data: { lastLoginAt: new Date() },
  });
}

// Search users
export async function searchUsers(
  query: string,
  options: PaginationOptions = {}
): Promise<PaginatedResult<User>> {
  const page = options.page || 1;
  const limit = options.limit || 20;
  const skip = (page - 1) * limit;

  const where: Prisma.UserWhereInput = {
    OR: [
      { name: { contains: query, mode: 'insensitive' } },
      { email: { contains: query, mode: 'insensitive' } },
      { city: { contains: query, mode: 'insensitive' } },
    ],
  };

  const [users, total] = await Promise.all([
    prisma.user.findMany({
      where,
      skip,
      take: limit,
      orderBy: { name: 'asc' },
    }),
    prisma.user.count({ where }),
  ]);

  return createPaginatedResult(users, total, page, limit);
}

// Get user with their plants
export async function getUserWithPlants(id: string) {
  return prisma.user.findUnique({
    where: { id },
    include: {
      ownedPlants: {
        orderBy: { registeredAt: 'desc' },
      },
    },
  });
}

// Get user with their farms
export async function getUserWithFarms(id: string) {
  return prisma.user.findUnique({
    where: { id },
    include: {
      verticalFarms: {
        include: {
          zones: true,
        },
      },
    },
  });
}

// Get user statistics
export async function getUserStats(id: string) {
  const [
    plantCount,
    farmCount,
    transportEventsSent,
    transportEventsReceived,
    supplyCommitments,
  ] = await Promise.all([
    prisma.plant.count({ where: { ownerId: id } }),
    prisma.verticalFarm.count({ where: { ownerId: id } }),
    prisma.transportEvent.count({ where: { senderId: id } }),
    prisma.transportEvent.count({ where: { receiverId: id } }),
    prisma.supplyCommitment.count({ where: { growerId: id } }),
  ]);

  return {
    plantCount,
    farmCount,
    transportEventsSent,
    transportEventsReceived,
    supplyCommitments,
  };
}
