import {
  PrismaClient,
  Prisma,
  Role,
  Game,
  Player,
  Club,
  User,
  GameData,
  Group
} from '@prisma/client';
import argon2 from 'argon2';

const database = new PrismaClient();

const seed = async () => {
  console.log('Starting database seeding...');

  const now = new Date();

  const passwordHash = await argon2.hash('IAmAPassword!');

  const adminUser = {
    email: 'noreply@agineek.com',
    emailVerifiedAt: now,
    passwordHash,
    firstName: 'Admin',
    lastName: '',
    phoneNumber: '8888888888',
    biography: '',
    role: Role.Admin
  };

  const dbAdminUser: User = await database.user.upsert({
    where: {
      email: adminUser.email
    },
    create: adminUser,
    update: adminUser
  });

  if (!dbAdminUser) {
    throw new Error('Failed to create Administrator user');
  }

  const testClub = {
    phoneId: 1,
    clubName: 'Test Club',
    owner: {
      connect: {
        id: dbAdminUser.id
      }
    }
  };

  let dbTestClub: Club | null = await database.club.findFirst({
    where: {
      clubName: testClub.clubName
    }
  });

  if (!dbTestClub) {
    dbTestClub = await database.club.create({
      data: testClub
    });
  } else {
    dbTestClub = await database.club.update({
      where: {
        id: dbTestClub.id
      },
      data: testClub
    });
  }

  const testGroup = {
    phoneId: 1,
    name: 'Test Group',
    description: 'This is a test group',
    club: {
      connect: {
        id: dbTestClub.id
      }
    }
  };

  let dbGroup: Group | null = await database.group.findFirst({
    where: {
      name: testGroup.name
    }
  });

  if (!dbGroup) {
    dbGroup = await database.group.create({
      data: testGroup
    });
  } else {
    dbGroup = await database.group.update({
      where: {
        id: dbGroup.id
      },
      data: testGroup
    });
  }

  const testPlayer = {
    phoneId: 1,
    email: 'test@agineek.com',
    rating: 1.0,
    phoneNumber: '305-555-5555',
    firstName: 'Test',
    lastName: 'Player',
    dateOfBirth: now,
    owner: {
      connect: {
        id: dbAdminUser.id
      }
    },
    club: {
      connect: {
        id: dbTestClub.id
      }
    },
    group: {
      connect: {
        id: dbGroup.id
      }
    }
  };

  const dbTestPlayer: Player = await database.player.upsert({
    where: {
      email: testPlayer.email
    },
    create: testPlayer,
    update: testPlayer
  });

  const testGame = {
    phoneId: 1,
    name: 'Test Game',
    notes: 'This is a test game...',
    sequence: '1,2,1,1,1,2,3,1',
    gameMode: 'Sequence',
    gameType: 'Single',
    gameTime: '60 minutes',
    delayTime: '5 minutes',
    numPads: 3,
    gameDescription: 'A Test Game',
    padLightUpTime: 5.0,
    scheduledDate: now,
    club: {
      connect: {
        id: dbTestClub.id
      }
    }
  };

  let dbTestGame: Game | null = await database.game.findFirst({
    where: {
      name: 'Test Game',
      scheduledDate: now
    }
  });

  if (!dbTestGame) {
    dbTestGame = await database.game.create({
      data: testGame
    });
  } else {
    dbTestGame = await database.game.update({
      where: {
        id: dbTestGame.id
      },
      data: testGame
    });
  }

  const testGameData = {
    hits: 5,
    misses: 3,
    accuracy: 5 / 8,
    timeSequence: '',
    padArrangement: 'Some Pad Arrangement',
    players: {
      connect: [{ id: dbTestPlayer.id }]
    },
    game: {
      connect: {
        id: dbTestGame.id
      }
    }
  };

  let dbTestGameData: GameData | null = await database.gameData.findFirst({
    where: {
      game: {
        id: dbTestGame.id
      }
    }
  });

  if (!dbTestGameData) {
    dbTestGameData = await database.gameData.create({
      data: testGameData
    });
  } else {
    dbTestGameData = await database.gameData.update({
      where: {
        id: dbTestGameData.id
      },
      data: testGameData
    });
  }
};

seed()
  .catch(console.error)
  .finally(() => {
    database.$disconnect();
  });
