#!/bin/bash

# Horse Racing Scraper - Project Initialization Script
# This script sets up the complete project structure, dependencies, and configuration

set -e  # Exit on error

echo "🏇 Initializing Horse Racing Scraper Project..."
echo ""

# Colors for output
GREEN='\033[0;32m'
BLUE='\033[0;34m'
YELLOW='\033[1;33m'
NC='\033[0m' # No Color

# Work in current directory
echo -e "${BLUE}📁 Initializing project in current directory${NC}"

# Create .gitignore
echo -e "${BLUE}📝 Creating .gitignore${NC}"
cat > .gitignore << 'EOF'
# Dependencies
node_modules/
.pnp
.pnp.js

# Environment variables
.env
.env.local
.env.*.local

# Build output
dist/
build/
*.tsbuildinfo

# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*

# IDE
.vscode/
.idea/
*.swp
*.swo
*~

# OS
.DS_Store
Thumbs.db

# Testing
coverage/
.nyc_output/

# Prisma
prisma/migrations/

# Temporary files
*.tmp
.cache/
EOF

# Initialize package.json
echo -e "${BLUE}📦 Initializing package.json${NC}"
cat > package.json << 'EOF'
{
  "name": "racing-scraper",
  "version": "1.0.0",
  "description": "Near-realtime horse racing data scraper for AUS/NZ thoroughbred and harness racing",
  "main": "dist/index.js",
  "scripts": {
    "dev": "tsx watch src/index.ts",
    "build": "tsc",
    "start": "node dist/index.js",
    "start:scheduler": "node dist/schedulers/index.js",
    "start:worker": "node dist/workers/index.js",
    "prisma:generate": "prisma generate",
    "prisma:migrate": "prisma migrate dev",
    "prisma:studio": "prisma studio",
    "test": "jest",
    "test:watch": "jest --watch",
    "test:coverage": "jest --coverage",
    "test:integration": "jest --testPathPattern=integration",
    "test:unit": "jest --testPathPattern=unit",
    "test:e2e": "jest --testPathPattern=e2e",
    "lint": "eslint src --ext .ts",
    "lint:fix": "eslint src --ext .ts --fix",
    "format": "prettier --write \"src/**/*.ts\"",
    "type-check": "tsc --noEmit",
    "metrics:dev": "node scripts/metrics-dashboard.js"
  },
  "keywords": [
    "horse-racing",
    "scraper",
    "data-collection",
    "elo-rating"
  ],
  "author": "Tom",
  "license": "MIT",
  "dependencies": {
    "@prisma/client": "^5.22.0",
    "axios": "^1.7.9",
    "axios-retry": "^4.5.0",
    "bottleneck": "^2.19.5",
    "bullmq": "^5.36.3",
    "dotenv": "^16.4.7",
    "ioredis": "^5.4.2",
    "luxon": "^3.5.0",
    "node-cron": "^3.0.3",
    "pino": "^9.6.0",
    "pino-pretty": "^13.0.0",
    "zod": "^3.23.8",
    "@opentelemetry/api": "^1.9.0",
    "@opentelemetry/sdk-node": "^0.54.2",
    "@opentelemetry/auto-instrumentations-node": "^0.51.1",
    "@opentelemetry/exporter-trace-otlp-http": "^0.54.2",
    "@opentelemetry/exporter-metrics-otlp-http": "^0.54.2",
    "prom-client": "^15.1.3"
  },
  "devDependencies": {
    "@types/jest": "^29.5.14",
    "@types/luxon": "^3.4.2",
    "@types/node": "^22.10.5",
    "@types/node-cron": "^3.0.11",
    "@typescript-eslint/eslint-plugin": "^8.19.1",
    "@typescript-eslint/parser": "^8.19.1",
    "eslint": "^9.18.0",
    "eslint-config-prettier": "^9.1.0",
    "jest": "^29.7.0",
    "prettier": "^3.4.2",
    "prisma": "^5.22.0",
    "ts-jest": "^29.2.5",
    "ts-node": "^10.9.2",
    "tsx": "^4.19.2",
    "typescript": "^5.7.3",
    "supertest": "^7.0.0",
    "@types/supertest": "^6.0.2",
    "nock": "^13.5.6"
  },
  "engines": {
    "node": ">=18.0.0",
    "npm": ">=9.0.0"
  }
}
EOF

# Create TypeScript configuration
echo -e "${BLUE}⚙️  Creating tsconfig.json${NC}"
cat > tsconfig.json << 'EOF'
{
  "compilerOptions": {
    "target": "ES2022",
    "module": "commonjs",
    "lib": ["ES2022"],
    "outDir": "./dist",
    "rootDir": "./src",
    "strict": true,
    "esModuleInterop": true,
    "skipLibCheck": true,
    "forceConsistentCasingInFileNames": true,
    "resolveJsonModule": true,
    "moduleResolution": "node",
    "declaration": true,
    "declarationMap": true,
    "sourceMap": true,
    "noUnusedLocals": true,
    "noUnusedParameters": true,
    "noImplicitReturns": true,
    "noFallthroughCasesInSwitch": true
  },
  "include": ["src/**/*"],
  "exclude": ["node_modules", "dist", "**/*.test.ts"]
}
EOF

# Create ESLint configuration
echo -e "${BLUE}🔍 Creating .eslintrc.json${NC}"
cat > .eslintrc.json << 'EOF'
{
  "parser": "@typescript-eslint/parser",
  "extends": [
    "eslint:recommended",
    "plugin:@typescript-eslint/recommended",
    "prettier"
  ],
  "plugins": ["@typescript-eslint"],
  "env": {
    "node": true,
    "es2022": true
  },
  "rules": {
    "@typescript-eslint/no-explicit-any": "warn",
    "@typescript-eslint/explicit-function-return-type": "off",
    "@typescript-eslint/no-unused-vars": ["error", { "argsIgnorePattern": "^_" }]
  }
}
EOF

# Create Prettier configuration
echo -e "${BLUE}💅 Creating .prettierrc${NC}"
cat > .prettierrc << 'EOF'
{
  "semi": true,
  "trailingComma": "es5",
  "singleQuote": true,
  "printWidth": 100,
  "tabWidth": 2,
  "useTabs": false,
  "arrowParens": "avoid"
}
EOF

# Create Jest configuration
echo -e "${BLUE}🧪 Creating jest.config.js${NC}"
cat > jest.config.js << 'EOF'
module.exports = {
  preset: 'ts-jest',
  testEnvironment: 'node',
  roots: ['<rootDir>/src'],
  testMatch: ['**/__tests__/**/*.ts', '**/?(*.)+(spec|test).ts'],
  transform: {
    '^.+\\.ts$': 'ts-jest',
  },
  collectCoverageFrom: [
    'src/**/*.ts',
    '!src/**/*.d.ts',
    '!src/**/*.test.ts',
    '!src/**/__tests__/**',
  ],
  coverageThreshold: {
    global: {
      branches: 70,
      functions: 70,
      lines: 70,
      statements: 70,
    },
  },
};
EOF

# Create environment template
echo -e "${BLUE}🔐 Creating .env.example${NC}"
cat > .env.example << 'EOF'
# Database
DATABASE_URL=postgresql://racing:racing123@localhost:5432/racing_db

# Redis
REDIS_URL=redis://localhost:6379

# TAB Affiliates API
TAB_API_BASE_URL=https://api.tab.com.au
TAB_API_KEY=your-tab-api-key

# Scheduling
MORNING_SCRAPE_CRON=0 6 * * *
TIMEZONE=Pacific/Auckland

# Rate Limiting
API_RATE_LIMIT_PER_MINUTE=100
API_RETRY_ATTEMPTS=3
API_RETRY_DELAY_MS=1000

# Feature Flags
ENABLE_HARNESS_RACING=true
ENABLE_THOROUGHBRED_RACING=true
ENABLE_AUS_RACING=true
ENABLE_NZ_RACING=true

# Logging
LOG_LEVEL=info
NODE_ENV=development

# Observability - OpenTelemetry
OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4318
OTEL_SERVICE_NAME=racing-scraper
OTEL_TRACES_SAMPLER=parentbased_traceidratio
OTEL_TRACES_SAMPLER_ARG=1.0
ENABLE_TRACING=true

# Observability - Metrics
ENABLE_METRICS=true
METRICS_PORT=9090
PROMETHEUS_ENDPOINT=/metrics

# Observability - Health Checks
HEALTH_CHECK_PORT=8080
ENABLE_HEALTH_CHECKS=true
EOF

# Create directory structure
echo -e "${BLUE}📂 Creating project structure${NC}"
mkdir -p src/{api,models,schedulers,workers,services,utils,config,__tests__}
mkdir -p prisma/{migrations}
mkdir -p docs
mkdir -p scripts

# Create Prisma schema
echo -e "${BLUE}🗄️  Creating Prisma schema${NC}"
cat > prisma/schema.prisma << 'EOF'
generator client {
  provider = "prisma-client-js"
}

datasource db {
  provider = "postgresql"
  url      = env("DATABASE_URL")
}

model Meeting {
  id                  String   @id @default(uuid()) @db.Uuid
  name                String   @db.VarChar(255)
  date                DateTime @db.Date
  country             String   @db.VarChar(3)
  state               String?  @db.VarChar(3)
  category            String   @db.VarChar(1) // 'T' or 'H'
  categoryName        String?  @db.VarChar(100)
  trackCondition      String?  @db.VarChar(50)
  weather             String?  @db.VarChar(50)
  videoChannels       Json?
  quaddie             Int[]
  earlyQuaddie        Int[]
  toteMeetingNumber   Int?
  toteStatus          String?  @db.VarChar(50)
  metadata            Json?
  createdAt           DateTime @default(now()) @db.Timestamptz(6)
  updatedAt           DateTime @updatedAt @db.Timestamptz(6)

  races Race[]

  @@index([date, country, category])
  @@map("meetings")
}

model Race {
  id              String   @id @default(uuid()) @db.Uuid
  meetingId       String   @db.Uuid
  raceNumber      Int
  name            String   @db.VarChar(255)
  startTime       DateTime @db.Timestamptz(6)
  toteStartTime   DateTime? @db.Time(6)
  distance        Int
  trackCondition  String?  @db.VarChar(50)
  weather         String?  @db.VarChar(50)
  status          String   @db.VarChar(50)
  country         String   @db.VarChar(3)
  state           String?  @db.VarChar(3)
  metadata        Json?
  createdAt       DateTime @default(now()) @db.Timestamptz(6)
  updatedAt       DateTime @updatedAt @db.Timestamptz(6)

  meeting Meeting  @relation(fields: [meetingId], references: [id], onDelete: Cascade)
  runners Runner[]
  scrapes Scrape[]
  results Result[]

  @@unique([meetingId, raceNumber])
  @@index([meetingId])
  @@index([startTime])
  @@index([status])
  @@map("races")
}

model Runner {
  id                     String    @id @default(uuid()) @db.Uuid
  raceId                 String    @db.Uuid
  runnerNumber           Int
  horseName              String    @db.VarChar(255)
  horseId                String?   @db.Uuid
  barrier                Int?
  weight                 Decimal?  @db.Decimal(5, 2)
  jockeyName             String?   @db.VarChar(255)
  jockeyId               String?   @db.Uuid
  jockeyWeightAllowance  Decimal?  @db.Decimal(4, 2)
  trainerName            String?   @db.VarChar(255)
  trainerId              String?   @db.Uuid
  form                   String?   @db.VarChar(50)
  lastStarts             Json?
  scratched              Boolean   @default(false)
  scratchedAt            DateTime? @db.Timestamptz(6)
  openingOdds            Decimal?  @db.Decimal(10, 2)
  currentOdds            Decimal?  @db.Decimal(10, 2)
  metadata               Json?
  createdAt              DateTime  @default(now()) @db.Timestamptz(6)
  updatedAt              DateTime  @updatedAt @db.Timestamptz(6)

  race    Race     @relation(fields: [raceId], references: [id], onDelete: Cascade)
  results Result[]

  @@unique([raceId, runnerNumber])
  @@index([raceId])
  @@map("runners")
}

model Result {
  id             String   @id @default(uuid()) @db.Uuid
  raceId         String   @db.Uuid
  runnerId       String   @db.Uuid
  finishPosition Int?
  margin         Decimal? @db.Decimal(10, 2)
  raceTime       Decimal? @db.Decimal(10, 3)
  winDividend    Decimal? @db.Decimal(10, 2)
  placeDividend  Decimal? @db.Decimal(10, 2)
  official       Boolean  @default(false)
  disqualified   Boolean  @default(false)
  metadata       Json?
  createdAt      DateTime @default(now()) @db.Timestamptz(6)

  race   Race   @relation(fields: [raceId], references: [id], onDelete: Cascade)
  runner Runner @relation(fields: [runnerId], references: [id], onDelete: Cascade)

  @@unique([raceId, runnerId])
  @@map("results")
}

model Scrape {
  id               String   @id @default(uuid()) @db.Uuid
  raceId           String   @db.Uuid
  scrapeType       String   @db.VarChar(50)
  scrapedAt        DateTime @default(now()) @db.Timestamptz(6)
  changesDetected  Json?
  success          Boolean  @default(true)
  errorMessage     String?  @db.Text

  race Race @relation(fields: [raceId], references: [id], onDelete: Cascade)

  @@index([raceId, scrapeType, scrapedAt])
  @@map("scrapes")
}
EOF

# Create basic config file
echo -e "${BLUE}⚙️  Creating config/index.ts${NC}"
cat > src/config/index.ts << 'EOF'
import dotenv from 'dotenv';
import { z } from 'zod';

dotenv.config();

const configSchema = z.object({
  database: z.object({
    url: z.string().url(),
  }),
  redis: z.object({
    url: z.string().url(),
  }),
  tabApi: z.object({
    baseUrl: z.string().url(),
    apiKey: z.string().optional(),
  }),
  scheduling: z.object({
    morningScrapeCron: z.string(),
    timezone: z.string(),
  }),
  rateLimiting: z.object({
    perMinute: z.number().int().positive(),
    retryAttempts: z.number().int().nonnegative(),
    retryDelayMs: z.number().int().positive(),
  }),
  features: z.object({
    enableHarnessRacing: z.boolean(),
    enableThoroughbredRacing: z.boolean(),
    enableAusRacing: z.boolean(),
    enableNzRacing: z.boolean(),
  }),
  logging: z.object({
    level: z.enum(['trace', 'debug', 'info', 'warn', 'error', 'fatal']),
  }),
  env: z.enum(['development', 'production', 'test']),
});

const config = configSchema.parse({
  database: {
    url: process.env.DATABASE_URL!,
  },
  redis: {
    url: process.env.REDIS_URL || 'redis://localhost:6379',
  },
  tabApi: {
    baseUrl: process.env.TAB_API_BASE_URL!,
    apiKey: process.env.TAB_API_KEY,
  },
  scheduling: {
    morningScrapeCron: process.env.MORNING_SCRAPE_CRON || '0 6 * * *',
    timezone: process.env.TIMEZONE || 'Pacific/Auckland',
  },
  rateLimiting: {
    perMinute: parseInt(process.env.API_RATE_LIMIT_PER_MINUTE || '100', 10),
    retryAttempts: parseInt(process.env.API_RETRY_ATTEMPTS || '3', 10),
    retryDelayMs: parseInt(process.env.API_RETRY_DELAY_MS || '1000', 10),
  },
  features: {
    enableHarnessRacing: process.env.ENABLE_HARNESS_RACING === 'true',
    enableThoroughbredRacing: process.env.ENABLE_THOROUGHBRED_RACING === 'true',
    enableAusRacing: process.env.ENABLE_AUS_RACING === 'true',
    enableNzRacing: process.env.ENABLE_NZ_RACING === 'true',
  },
  logging: {
    level: (process.env.LOG_LEVEL || 'info') as 'info',
  },
  env: (process.env.NODE_ENV || 'development') as 'development',
});

export default config;
EOF

# Create logger utility
echo -e "${BLUE}📝 Creating utils/logger.ts${NC}"
cat > src/utils/logger.ts << 'EOF'
import pino from 'pino';
import config from '../config';

const logger = pino({
  level: config.logging.level,
  transport: {
    target: 'pino-pretty',
    options: {
      colorize: true,
      translateTime: 'SYS:standard',
      ignore: 'pid,hostname',
    },
  },
});

export default logger;
EOF

# Create basic index.ts
echo -e "${BLUE}🚀 Creating src/index.ts${NC}"
cat > src/index.ts << 'EOF'
import logger from './utils/logger';
import config from './config';

async function main() {
  logger.info('🏇 Horse Racing Scraper starting...');
  logger.info('Environment:', config.env);
  logger.info('Features:', config.features);
  
  // TODO: Initialize services, schedulers, workers
  
  logger.info('✅ Application initialized successfully');
}

main().catch(error => {
  logger.error('Failed to start application:', error);
  process.exit(1);
});
EOF

# Create README
echo -e "${BLUE}📖 Creating README.md${NC}"
cat > README.md << 'EOF'
# 🏇 Horse Racing Data Scraper

Near-realtime horse racing data collection system for Australian and New Zealand thoroughbred and harness racing.

## 📋 Overview

This system scrapes race data from TAB Affiliates API, collecting meeting, race, and runner information throughout the day. The data is used for future Elo rating calculations to generate win/place probabilities.

## 🚀 Quick Start

### Prerequisites

- Node.js >= 18.0.0
- PostgreSQL >= 14
- Redis >= 6.0
- npm >= 9.0.0

### Installation

```bash
# Clone the repository
git clone <repository-url>
cd racing-scraper

# Install dependencies
npm install

# Set up environment variables
cp .env.example .env
# Edit .env with your configuration

# Generate Prisma client
npm run prisma:generate

# Run database migrations
npm run prisma:migrate

# Start development server
npm run dev
```

## 📁 Project Structure

```
racing-scraper/
├── src/
│   ├── api/              # API client implementations
│   ├── config/           # Configuration
│   ├── models/           # Prisma client and types
│   ├── schedulers/       # Cron jobs
│   ├── services/         # Business logic
│   ├── utils/            # Utilities and helpers
│   ├── workers/          # Queue workers
│   └── index.ts          # Application entry point
├── prisma/
│   └── schema.prisma     # Database schema
├── docs/                 # Documentation
├── scripts/              # Utility scripts
└── tests/                # Test files
```

## 🔧 Development

```bash
# Run in development mode with watch
npm run dev

# Build for production
npm run build

# Start production server
npm start

# Run tests
npm test

# Run tests with coverage
npm test:coverage

# Lint code
npm run lint

# Format code
npm run format

# Type check
npm run type-check
```

## 📊 Database

```bash
# Open Prisma Studio (database GUI)
npm run prisma:studio

# Create a new migration
npm run prisma:migrate

# Reset database (⚠️ destroys all data)
npx prisma migrate reset
```

## 🗓️ Data Collection Flow

1. **Morning Scrape (6:00 AM)**: Fetch all meetings and races for the day
2. **Pre-Race Updates (T-60, T-15)**: Check for scratches and condition changes
3. **Post-Race (T+5)**: Collect race results

## 📚 Documentation

See [PROJECT_BRIEF.md](./PROJECT_BRIEF.md) for comprehensive project documentation including:
- Technical architecture
- Database schema
- API specifications
- Implementation phases
- Configuration options

## 🔐 Environment Variables

See `.env.example` for all available configuration options.

## 🧪 Testing

```bash
# Run all tests
npm test

# Run tests in watch mode
npm test:watch

# Run with coverage
npm test:coverage
```

## 📝 License

MIT

## 👥 Authors

- Tom

## 🤝 Contributing

See [CONTRIBUTING.md](./CONTRIBUTING.md) for contribution guidelines.
EOF

# Create docker-compose for local development
echo -e "${BLUE}🐳 Creating docker-compose.yml${NC}"
cat > docker-compose.yml << 'EOF'
version: '3.8'

services:
  # PostgreSQL Database
  postgres:
    image: postgres:16-alpine
    container_name: racing-postgres
    environment:
      POSTGRES_USER: racing
      POSTGRES_PASSWORD: racing123
      POSTGRES_DB: racing_db
    ports:
      - "5432:5432"
    volumes:
      - postgres_data:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U racing"]
      interval: 10s
      timeout: 5s
      retries: 5
    networks:
      - racing-network

  # Redis for Queue and Cache
  redis:
    image: redis:7-alpine
    container_name: racing-redis
    ports:
      - "6379:6379"
    volumes:
      - redis_data:/data
    healthcheck:
      test: ["CMD", "redis-cli", "ping"]
      interval: 10s
      timeout: 5s
      retries: 5
    networks:
      - racing-network

  # Jaeger for Distributed Tracing
  jaeger:
    image: jaegertracing/all-in-one:latest
    container_name: racing-jaeger
    environment:
      - COLLECTOR_OTLP_ENABLED=true
    ports:
      - "16686:16686"  # Jaeger UI
      - "4318:4318"    # OTLP HTTP receiver
      - "4317:4317"    # OTLP gRPC receiver
    networks:
      - racing-network

  # Prometheus for Metrics
  prometheus:
    image: prom/prometheus:latest
    container_name: racing-prometheus
    command:
      - '--config.file=/etc/prometheus/prometheus.yml'
      - '--storage.tsdb.path=/prometheus'
      - '--web.console.libraries=/usr/share/prometheus/console_libraries'
      - '--web.console.templates=/usr/share/prometheus/consoles'
    ports:
      - "9091:9090"  # Changed to avoid conflicts
    volumes:
      - ./prometheus.yml:/etc/prometheus/prometheus.yml:ro
      - prometheus_data:/prometheus
    networks:
      - racing-network
    depends_on:
      - app

  # Grafana for Dashboards
  grafana:
    image: grafana/grafana:latest
    container_name: racing-grafana
    environment:
      - GF_SECURITY_ADMIN_USER=admin
      - GF_SECURITY_ADMIN_PASSWORD=admin
      - GF_USERS_ALLOW_SIGN_UP=false
    ports:
      - "3000:3000"
    volumes:
      - grafana_data:/var/lib/grafana
      - ./grafana/provisioning:/etc/grafana/provisioning:ro
    networks:
      - racing-network
    depends_on:
      - prometheus

  # Application (optional - can run locally instead)
  app:
    build:
      context: .
      dockerfile: Dockerfile
    container_name: racing-app
    environment:
      - NODE_ENV=development
      - DATABASE_URL=postgresql://racing:racing123@postgres:5432/racing_db
      - REDIS_URL=redis://redis:6379
      - OTEL_EXPORTER_OTLP_ENDPOINT=http://jaeger:4318
      - ENABLE_TRACING=true
      - ENABLE_METRICS=true
    ports:
      - "8080:8080"  # Health checks
      - "9090:9090"  # Metrics endpoint
    volumes:
      - .:/app
      - /app/node_modules
    networks:
      - racing-network
    depends_on:
      postgres:
        condition: service_healthy
      redis:
        condition: service_healthy
    command: npm run dev

volumes:
  postgres_data:
  redis_data:
  prometheus_data:
  grafana_data:

networks:
  racing-network:
    driver: bridge
EOF

# Create Prometheus config
echo -e "${BLUE}📊 Creating prometheus.yml${NC}"
cat > prometheus.yml << 'EOF'
global:
  scrape_interval: 15s
  evaluation_interval: 15s

scrape_configs:
  - job_name: 'racing-scraper'
    static_configs:
      - targets: ['app:9090']
    metrics_path: '/metrics'
EOF

# Create Grafana provisioning directory structure
echo -e "${BLUE}📈 Creating Grafana provisioning${NC}"
mkdir -p grafana/provisioning/{datasources,dashboards}

cat > grafana/provisioning/datasources/prometheus.yml << 'EOF'
apiVersion: 1

datasources:
  - name: Prometheus
    type: prometheus
    access: proxy
    url: http://prometheus:9090
    isDefault: true
    editable: true
EOF

cat > grafana/provisioning/dashboards/dashboard.yml << 'EOF'
apiVersion: 1

providers:
  - name: 'Racing Scraper'
    orgId: 1
    folder: ''
    type: file
    disableDeletion: false
    updateIntervalSeconds: 10
    allowUiUpdates: true
    options:
      path: /etc/grafana/provisioning/dashboards
EOF

# Create Dockerfile
echo -e "${BLUE}🐳 Creating Dockerfile${NC}"
cat > Dockerfile << 'EOF'
FROM node:18-alpine

WORKDIR /app

# Install dependencies
COPY package*.json ./
RUN npm ci

# Copy source
COPY . .

# Generate Prisma client
RUN npx prisma generate

# Build TypeScript
RUN npm run build

# Expose ports
EXPOSE 8080 9090

CMD ["npm", "start"]
EOF

# Create .dockerignore
cat > .dockerignore << 'EOF'
node_modules
dist
.env
*.log
.git
.github
coverage
.vscode
*.md
EOF

# Create a setup script for first-time users
echo -e "${BLUE}🛠️  Creating setup.sh${NC}"
cat > scripts/setup.sh << 'EOF'
#!/bin/bash

echo "🏇 Setting up Horse Racing Scraper..."

# Check for required tools
command -v node >/dev/null 2>&1 || { echo "❌ Node.js is required but not installed. Aborting."; exit 1; }
command -v npm >/dev/null 2>&1 || { echo "❌ npm is required but not installed. Aborting."; exit 1; }
command -v docker >/dev/null 2>&1 || { echo "⚠️  Docker not found. You'll need to set up PostgreSQL and Redis manually."; }

echo "✅ Required tools found"

# Install dependencies
echo "📦 Installing dependencies..."
npm install

# Start Docker containers if Docker is available
if command -v docker-compose >/dev/null 2>&1; then
  echo "🐳 Starting Docker containers..."
  docker-compose up -d
  
  echo "⏳ Waiting for databases to be ready..."
  sleep 10
fi

# Copy env file if it doesn't exist
if [ ! -f .env ]; then
  echo "📝 Creating .env file from template..."
  cp .env.example .env
  echo "⚠️  Please edit .env with your API keys and configuration"
fi

# Generate Prisma client
echo "🔧 Generating Prisma client..."
npm run prisma:generate

# Run migrations
echo "🗄️  Running database migrations..."
npm run prisma:migrate

echo ""
echo "✅ Setup complete!"
echo ""
echo "Next steps:"
echo "1. Edit .env with your API keys"
echo "2. Run 'npm run dev' to start development server"
echo "3. Open http://localhost:5555 for Prisma Studio (database GUI)"
echo ""
EOF

chmod +x scripts/setup.sh

# Create CONTRIBUTING guide
echo -e "${BLUE}📘 Creating CONTRIBUTING.md${NC}"
cat > CONTRIBUTING.md << 'EOF'
# Contributing to Horse Racing Scraper

## Development Workflow

1. Create a feature branch from `main`
2. Make your changes
3. Write tests for new functionality
4. Ensure all tests pass: `npm test`
5. Lint your code: `npm run lint`
6. Format your code: `npm run format`
7. Submit a pull request

## Code Style

- Use TypeScript for all new code
- Follow ESLint and Prettier configurations
- Write descriptive commit messages
- Add JSDoc comments for public functions
- Maintain test coverage above 70%

## Testing

- Write unit tests for business logic
- Write integration tests for API clients
- Mock external dependencies
- Use meaningful test descriptions

## Commit Messages

Follow conventional commits:
- `feat:` New feature
- `fix:` Bug fix
- `docs:` Documentation changes
- `refactor:` Code refactoring
- `test:` Test changes
- `chore:` Build/tooling changes
EOF

# Summary
echo ""
echo -e "${GREEN}✅ Project initialization complete!${NC}"
echo ""
echo "Next steps:"
echo "  1. Copy your API specification files (openapi.json, etc.) to this directory"
echo "  2. Copy claude.md and WORKING_CONTEXT.md to this directory"
echo "  3. Create reference-data/claude-reference/ and copy documentation there"
echo "  4. Edit .env with your API keys and configuration"
echo "  5. Run: npm install"
echo "  6. Run: docker-compose up -d  (to start PostgreSQL and Redis)"
echo "  7. Run: npm run prisma:migrate  (to set up database)"
echo "  8. Run: npm run dev  (to start development)"
echo ""
echo "Or use the automated setup script:"
echo "  ./scripts/setup.sh"
echo ""
echo -e "${BLUE}📖 Read reference-data/claude-reference/PROJECT_BRIEF.md for detailed documentation${NC}"
echo ""
echo -e "${GREEN}🏇 Happy racing!${NC}"
