import { call, os } from "@orpc/server";
import { z } from "zod";
import { randomUUID } from "crypto";
import { createKV } from "../lib/create-kv.js";
import { config } from "dotenv";

// Load environment variables from .env file
config();

const UserSchema = z.object({
  id: z.string(),
  username: z.string().min(3, "Benutzername muss mindestens 3 Zeichen lang sein"),
  email: z.string().email("Ungültige E-Mail-Adresse"),
  passwordHash: z.string(),
  role: z.enum(["customer", "owner"]),
  createdAt: z.string(),
});

const SessionSchema = z.object({
  id: z.string(),
  userId: z.string(),
  expiresAt: z.string(),
  createdAt: z.string(),
});

type User = z.output<typeof UserSchema>;
type Session = z.output<typeof SessionSchema>;

const usersKV = createKV<User>("users");
const sessionsKV = createKV<Session>("sessions");

// Simple password hashing (in production, use bcrypt or similar)
const hashPassword = (password: string): string => {
  return Buffer.from(password).toString('base64');
};

const verifyPassword = (password: string, hash: string): boolean => {
  return hashPassword(password) === hash;
};

// Export hashPassword for external use (e.g., generating hashes for .env)
export const generatePasswordHash = hashPassword;

// Initialize default owner account
const initializeOwner = async () => {
  const existingUsers = await usersKV.getAllItems();
  if (existingUsers.length === 0) {
    const ownerId = randomUUID();
    
    // Get admin credentials from environment variables
    const adminUsername = process.env.ADMIN_USERNAME || "owner";
    const adminPasswordHash = process.env.ADMIN_PASSWORD_HASH || hashPassword("admin123");
    const adminEmail = process.env.ADMIN_EMAIL || "owner@stargirlnails.de";
    
    const owner: User = {
      id: ownerId,
      username: adminUsername,
      email: adminEmail,
      passwordHash: adminPasswordHash,
      role: "owner",
      createdAt: new Date().toISOString(),
    };
    await usersKV.setItem(ownerId, owner);
    
    console.log(`✅ Admin account created: username="${adminUsername}", email="${adminEmail}"`);
  }
};

// Initialize on module load
initializeOwner();

const login = os
  .input(z.object({
    username: z.string(),
    password: z.string(),
  }))
  .handler(async ({ input }) => {
    const users = await usersKV.getAllItems();
    const user = users.find(u => u.username === input.username);
    
    if (!user || !verifyPassword(input.password, user.passwordHash)) {
      throw new Error("Invalid credentials");
    }

    // Create session
    const sessionId = randomUUID();
    const expiresAt = new Date();
    expiresAt.setHours(expiresAt.getHours() + 24); // 24 hours

    const session: Session = {
      id: sessionId,
      userId: user.id,
      expiresAt: expiresAt.toISOString(),
      createdAt: new Date().toISOString(),
    };

    await sessionsKV.setItem(sessionId, session);

    return {
      sessionId,
      user: {
        id: user.id,
        username: user.username,
        email: user.email,
        role: user.role,
      },
    };
  });

const logout = os
  .input(z.string()) // sessionId
  .handler(async ({ input }) => {
    await sessionsKV.removeItem(input);
    return { success: true };
  });

const verifySession = os
  .input(z.string()) // sessionId
  .handler(async ({ input }) => {
    const session = await sessionsKV.getItem(input);
    if (!session) {
      throw new Error("Invalid session");
    }

    if (new Date(session.expiresAt) < new Date()) {
      await sessionsKV.removeItem(input);
      throw new Error("Session expired");
    }

    const user = await usersKV.getItem(session.userId);
    if (!user) {
      throw new Error("User not found");
    }

    return {
      user: {
        id: user.id,
        username: user.username,
        email: user.email,
        role: user.role,
      },
    };
  });

const changePassword = os
  .input(z.object({
    sessionId: z.string(),
    currentPassword: z.string(),
    newPassword: z.string(),
  }))
  .handler(async ({ input }) => {
    const session = await sessionsKV.getItem(input.sessionId);
    if (!session) {
      throw new Error("Invalid session");
    }

    const user = await usersKV.getItem(session.userId);
    if (!user) {
      throw new Error("User not found");
    }

    if (!verifyPassword(input.currentPassword, user.passwordHash)) {
      throw new Error("Current password is incorrect");
    }

    const updatedUser = {
      ...user,
      passwordHash: hashPassword(input.newPassword),
    };

    await usersKV.setItem(user.id, updatedUser);
    return { success: true };
  });

export const router = {
  login,
  logout,
  verifySession,
  changePassword,
};