import { eq, and } from "drizzle-orm";
import db from "../../db";
import { branches, userBranches, users } from "../../db/schema";

export interface CreateBranchParams {
  companyId: string;
  name: string;
  address?: string;
  city?: string;
  country?: string;
}

export interface UpdateBranchParams {
  name?: string;
  address?: string;
  city?: string;
  country?: string;
}

/**
 * Сервис для работы с филиалами
 */
export const branchService = {
  /**
   * Создать филиал
   */
  async create(params: CreateBranchParams) {
    const [branch] = await db
      .insert(branches)
      .values({
        companyId: params.companyId,
        name: params.name,
        address: params.address,
        city: params.city,
        country: params.country,
      })
      .returning();

    return branch;
  },

  /**
   * Получить все филиалы компании
   */
  async findByCompanyId(companyId: string) {
    const companyBranches = await db.query.branches.findMany({
      where: eq(branches.companyId, companyId),
      with: {
        company: true,
      },
      orderBy: (branches, { asc }) => [asc(branches.name)],
    });

    return companyBranches;
  },

  /**
   * Найти филиал по ID
   */
  async findById(branchId: string) {
    const branch = await db.query.branches.findFirst({
      where: eq(branches.id, branchId),
      with: {
        company: true,
      },
    });

    return branch || null;
  },

  /**
   * Получить филиалы пользователя
   */
  async findByUserId(userId: string) {
    const userBranchRecords = await db.query.userBranches.findMany({
      where: eq(userBranches.userId, userId),
      with: {
        branch: {
          with: {
            company: true,
          },
        },
      },
    });

    return userBranchRecords.map((record) => record.branch);
  },

  /**
   * Обновить филиал
   */
  async update(branchId: string, params: UpdateBranchParams) {
    const updateData: any = {
      updatedAt: new Date(),
    };

    if (params.name) {
      updateData.name = params.name;
    }

    if (params.address !== undefined) {
      updateData.address = params.address;
    }

    if (params.city !== undefined) {
      updateData.city = params.city;
    }

    if (params.country !== undefined) {
      updateData.country = params.country;
    }

    const [updatedBranch] = await db
      .update(branches)
      .set(updateData)
      .where(eq(branches.id, branchId))
      .returning();

    return updatedBranch;
  },

  /**
   * Удалить филиал
   */
  async delete(branchId: string) {
    await db.delete(branches).where(eq(branches.id, branchId));
  },

  /**
   * Привязать пользователя к филиалу
   */
  async assignUserToBranch(userId: string, branchId: string) {
    const [userBranch] = await db
      .insert(userBranches)
      .values({
        userId,
        branchId,
      })
      .returning();

    return userBranch;
  },

  /**
   * Отвязать пользователя от филиала
   */
  async removeUserFromBranch(userId: string, branchId: string) {
    await db
      .delete(userBranches)
      .where(
        and(
          eq(userBranches.userId, userId),
          eq(userBranches.branchId, branchId)
        )
      );
  },

  /**
   * Установить текущий филиал для пользователя
   */
  async setUserCurrentBranch(userId: string, branchId: string) {
    // Проверить, что пользователь привязан к этому филиалу
    const userBranch = await db.query.userBranches.findFirst({
      where: and(
        eq(userBranches.userId, userId),
        eq(userBranches.branchId, branchId)
      ),
    });

    if (!userBranch) {
      throw new Error("User is not assigned to this branch");
    }

    // Обновить текущий филиал пользователя
    const [updatedUser] = await db
      .update(users)
      .set({
        currentBranchId: branchId,
        updatedAt: new Date(),
      })
      .where(eq(users.id, userId))
      .returning();

    return updatedUser;
  },

  /**
   * Получить пользователей филиала
   */
  async getUsersByBranchId(branchId: string) {
    const branchUsers = await db.query.userBranches.findMany({
      where: eq(userBranches.branchId, branchId),
      with: {
        user: {
          columns: {
            id: true,
            email: true,
            fullName: true,
            role: true,
            currentBranchId: true,
          },
        },
      },
    });

    return branchUsers.map((record) => record.user);
  },
};
