# Code Style Guide

This document defines the code formatting and linting standards for the HelloTax AI project.

## Python Code Standards

### Formatting Tool: Black

**Configuration:**
- Line length: 100 characters
- Target Python versions: 3.11+
- String normalization: enabled (double quotes)

**Usage:**
```bash
# Format a single file
black path/to/file.py

# Format a directory
black path/to/directory/

# Check without modifying
black --check path/to/directory/
```

### Linting Tool: Ruff

Ruff replaces flake8, isort, and pylint with a single fast tool.

**Configuration:**
- Line length: 100 characters
- Enabled rules: pycodestyle (E, W), pyflakes (F), isort (I), pep8-naming (N)
- Auto-fix: enabled for safe fixes

**Usage:**
```bash
# Lint and show issues
ruff check path/to/directory/

# Auto-fix issues
ruff check --fix path/to/directory/

# Format imports
ruff check --select I --fix path/to/directory/
```

### Import Ordering

Imports must be organized in three groups, separated by blank lines:

1. **Standard library imports**
2. **Third-party library imports**
3. **Local application imports**

**Example:**
```python
import os
import sys
from typing import Optional

import fastapi
from sqlalchemy import Column

from app.models import User
from app.utils import helper
```

### Naming Conventions

- **Functions and variables**: `snake_case`
- **Classes**: `PascalCase`
- **Constants**: `UPPER_SNAKE_CASE`
- **Private attributes**: `_leading_underscore`
- **Module names**: `lowercase` or `snake_case`

**Example:**
```python
MAX_RETRY_COUNT = 3

class UserService:
    def __init__(self):
        self._cache = {}
    
    def get_user_by_id(self, user_id: int) -> Optional[User]:
        pass
```

### Type Annotations

Use type hints for function signatures and class attributes:

```python
from typing import Optional, List, Dict

def process_users(
    user_ids: List[int],
    options: Optional[Dict[str, str]] = None
) -> List[User]:
    pass
```

### PEP 8 Guidelines

- Maximum line length: 100 characters (enforced by Black)
- Use 4 spaces for indentation (never tabs)
- Two blank lines between top-level definitions
- One blank line between method definitions
- Avoid trailing whitespace

## TypeScript/Vue Code Standards

### Formatting Tool: Prettier

**Configuration:**
- Print width: 100 characters
- Tab width: 2 spaces
- Use single quotes: true
- Semicolons: true
- Trailing commas: es5

**Usage:**
```bash
# Format files
pnpm prettier --write "src/**/*.{ts,vue,js}"

# Check without modifying
pnpm prettier --check "src/**/*.{ts,vue,js}"
```

### Linting Tool: ESLint

**Configuration:**
- ESLint 9.x with flat config
- Vue 3 plugin
- TypeScript ESLint parser
- Recommended rules enabled

**Usage:**
```bash
# Lint files
pnpm eslint "src/**/*.{ts,vue,js}"

# Auto-fix issues
pnpm eslint --fix "src/**/*.{ts,vue,js}"
```

### Component Naming

**Vue Components:**
- Use `PascalCase` for component names
- Multi-word component names (avoid single-word names)

**Example:**
```typescript
// Good
UserProfile.vue
DataTable.vue
NavigationBar.vue

// Avoid
User.vue
Table.vue
Nav.vue
```

### File Naming

- **Vue components**: `PascalCase.vue` (e.g., `UserProfile.vue`)
- **TypeScript files**: `kebab-case.ts` (e.g., `user-service.ts`)
- **Composables**: `use-*.ts` (e.g., `use-auth.ts`)
- **Types**: `*.types.ts` (e.g., `user.types.ts`)

### Type Definitions

Use TypeScript interfaces and types for all data structures:

```typescript
interface User {
  id: number;
  name: string;
  email: string;
  role: UserRole;
}

type UserRole = 'admin' | 'user' | 'guest';

function getUser(id: number): Promise<User> {
  // implementation
}
```

### Vue Component Structure

Organize Vue 3 Composition API components in this order:

```vue
<script setup lang="ts">
// 1. Imports
import { ref, computed, onMounted } from 'vue';
import { useRouter } from 'vue-router';

// 2. Props and emits
const props = defineProps<{
  userId: number;
}>();

const emit = defineEmits<{
  update: [user: User];
}>();

// 3. Composables
const router = useRouter();

// 4. Reactive state
const user = ref<User | null>(null);

// 5. Computed properties
const displayName = computed(() => user.value?.name ?? 'Unknown');

// 6. Methods
function handleUpdate() {
  // implementation
}

// 7. Lifecycle hooks
onMounted(() => {
  // initialization
});
</script>

<template>
  <!-- Template content -->
</template>

<style scoped>
/* Component styles */
</style>
```

## Tool Usage Guide

### Running Format/Lint on All Code

Use the automated scripts in the `scripts/` directory:

```bash
# Check all code (preview changes)
./scripts/format-lint-all.sh check

# Format all code (apply changes)
./scripts/format-lint-all.sh fix
```

### Running Format/Lint on Python Only

```bash
# Check Python code
./scripts/format-lint-python.sh check

# Format Python code
./scripts/format-lint-python.sh fix
```

### Running Format/Lint on Frontend Only

```bash
# Check frontend code
./scripts/format-lint-frontend.sh check

# Format frontend code
./scripts/format-lint-frontend.sh fix
```

### Per-Module Usage

**Python modules:**
```bash
cd base_platform/
source venv/bin/activate  # if using virtual environment
black .
ruff check --fix .
```

**Frontend modules:**
```bash
cd saas_portal/frontend/
pnpm prettier --write "src/**/*.{ts,vue,js}"
pnpm eslint --fix "src/**/*.{ts,vue,js}"
```

## IDE Integration

### VS Code

Install these extensions:
- Python: `ms-python.black-formatter`, `charliermarsh.ruff`
- Frontend: `esbenp.prettier-vscode`, `dbaeumer.vscode-eslint`

**Settings (.vscode/settings.json):**
```json
{
  "[python]": {
    "editor.defaultFormatter": "ms-python.black-formatter",
    "editor.formatOnSave": true,
    "editor.codeActionsOnSave": {
      "source.organizeImports": true
    }
  },
  "[typescript]": {
    "editor.defaultFormatter": "esbenp.prettier-vscode",
    "editor.formatOnSave": true
  },
  "[vue]": {
    "editor.defaultFormatter": "esbenp.prettier-vscode",
    "editor.formatOnSave": true
  }
}
```

### PyCharm / WebStorm

**Python:**
- Settings → Tools → Black → Enable on save
- Settings → Tools → Ruff → Enable linting

**Frontend:**
- Settings → Languages & Frameworks → JavaScript → Prettier → Enable on save
- Settings → Languages & Frameworks → JavaScript → Code Quality Tools → ESLint → Enable

## Pre-commit Hooks (Optional)

To automatically format code before commits, install pre-commit hooks:

```bash
# Install pre-commit
pip install pre-commit

# Install hooks
pre-commit install

# Run manually
pre-commit run --all-files
```

## Configuration Files

All format/lint tools are configured at the project root:

- **Python**: `pyproject.toml`
- **Prettier**: `.prettierrc.json`, `.prettierignore`
- **ESLint**: `eslint.config.js`
- **Dependencies**: `package.json` (frontend), `requirements.txt` (Python modules)

## Best Practices

1. **Format before committing**: Always run format/lint before creating commits
2. **Use automated scripts**: Prefer `./scripts/format-lint-all.sh` over manual commands
3. **Enable IDE formatting**: Configure your IDE to format on save
4. **Review changes**: After formatting, review git diff to ensure only style changes
5. **Run tests**: After major formatting changes, run test suites to verify functionality

## Troubleshooting

**Black and Ruff not found:**
- Ensure tools are installed in the module's virtual environment
- Activate the virtual environment before running commands

**ESLint/Prettier not found:**
- Run `pnpm install` in the project root
- Ensure you're using pnpm (not npm or yarn)

**Formatting conflicts:**
- Black and Prettier are opinionated and rarely conflict
- If conflicts occur, Black/Prettier takes precedence over linters

**Large diffs after formatting:**
- This is expected on first run
- Review changes carefully
- Consider formatting in smaller batches if needed
