import { postgresAdapter } from '@payloadcms/db-postgres'
import { lexicalEditor } from '@payloadcms/richtext-lexical'
import path from 'path'
import { buildConfig } from 'payload'
import { fileURLToPath } from 'url'
import { s3Storage } from '@payloadcms/storage-s3'

import { Tenants } from './collections/Tenants'
import Users from './collections/Users'
import { Residents } from './collections/Residents'
import { MealOrders } from './collections/MealOrders'
import { Meals } from './collections/Meals'
import { Media } from './collections/Media'
import { multiTenantPlugin } from '@payloadcms/plugin-multi-tenant'
import { isSuperAdmin } from './access/isSuperAdmin'
import type { Config } from './payload-types'
import { getUserTenantIDs } from './utilities/getUserTenantIDs'
import { seed } from './seed'

const filename = fileURLToPath(import.meta.url)
const dirname = path.dirname(filename)

// Use PostgreSQL when DATABASE_URI is set, SQLite only for local development
// Migration commands:
//   pnpm payload migrate:create  - Create migration file
//   pnpm payload migrate         - Run pending migrations
//   pnpm payload migrate:fresh   - Drop all & re-run migrations
//   pnpm payload migrate:reset   - Rollback all migrations
//   pnpm payload migrate:status  - Check migration status
const getDatabaseAdapter = async () => {
  if (process.env.DATABASE_URI) {
    // Conditionally import migrations only when using PostgreSQL
    const { migrations } = await import('./migrations')
    return postgresAdapter({
      pool: {
        connectionString: process.env.DATABASE_URI,
      },
      // Use migration files from src/migrations/ instead of auto-push
      push: false,
      migrationDir: path.resolve(dirname, 'migrations'),
      prodMigrations: migrations,
    })
  }

  // Only load SQLite in development (no DATABASE_URI set)
  // Dynamic import to avoid loading libsql in production/Docker
  const { sqliteAdapter } = await import('@payloadcms/db-sqlite')
  return sqliteAdapter({
    client: {
      url: 'file:./meal-planner.db',
    },
    // Use push mode for SQLite in development (auto-sync schema)
    push: true,
  })
}
// eslint-disable-next-line no-restricted-exports
export default buildConfig({
  admin: {
    user: 'users',
    meta: {
      titleSuffix: '- Meal Planner',
    },
    components: {
      views: {
        kitchenDashboard: {
          Component: '@/app/(payload)/admin/views/KitchenDashboard#KitchenDashboard',
          path: '/kitchen-dashboard',
        },
      },
    },
  },
  collections: [Users, Tenants, Residents, MealOrders, Meals, Media],
  db: await getDatabaseAdapter(),
  onInit: async (payload) => {
    // Run migrations automatically on startup (for Docker/production)
    payload.logger.info('Running database migrations...')
    try {
      await payload.db.migrate()
      payload.logger.info('Migrations completed successfully')
    } catch (err) {
      const message = err instanceof Error ? err.message : String(err)
      payload.logger.error(`Migration failed: ${message}`)
      // Don't throw - migrations may already be applied
    }

    // Seed database if SEED_DB is set
    if (process.env.SEED_DB) {
      await seed(payload)
    }
  },
  editor: lexicalEditor({}),
  graphQL: {
    schemaOutputFile: path.resolve(dirname, 'generated-schema.graphql'),
  },
  secret: process.env.PAYLOAD_SECRET as string,
  typescript: {
    outputFile: path.resolve(dirname, 'payload-types.ts'),
  },
  plugins: [
    // Conditionally add S3 storage when MINIO_ENDPOINT is set (Docker environment)
    ...(process.env.MINIO_ENDPOINT
      ? [
          s3Storage({
            collections: {
              media: true,
            },
            bucket: process.env.S3_BUCKET || 'meal-planner',
            config: {
              endpoint: process.env.MINIO_ENDPOINT,
              region: process.env.S3_REGION || 'us-east-1',
              credentials: {
                accessKeyId: process.env.S3_ACCESS_KEY_ID || '',
                secretAccessKey: process.env.S3_SECRET_ACCESS_KEY || '',
              },
              forcePathStyle: true, // Required for MinIO
            },
          }),
        ]
      : []),
    multiTenantPlugin<Config>({
      collections: {
        // Enable multi-tenancy for residents, meal orders, and meals
        residents: {},
        'meal-orders': {},
        meals: {},
      },
      tenantField: {
        access: {
          read: () => true,
          update: ({ req }) => {
            if (isSuperAdmin(req.user)) {
              return true
            }
            return getUserTenantIDs(req.user).length > 0
          },
        },
      },
      tenantsArrayField: {
        includeDefaultField: false,
      },
      userHasAccessToAllTenants: (user) => isSuperAdmin(user),
    }),
  ],
})
