D:\host\scoreman.in\assisi2026\certificate_list_export.php

<?php
// download_certificate_list.php
// CSV with ALL event columns (not just "highest").
// GET: repdistrict (required), appnos (optional comma-separated), prefix (optional)
// Sort: Team -> Discipline -> agorder -> Gender (Girls first) -> AppNo

date_default_timezone_set('Asia/Kolkata');
header('Content-Type: text/csv; charset=UTF-8');

require_once __DIR__ . '/dbconnect.php'; // must define $con (mysqli)

if (!($con instanceof mysqli)) {
    http_response_code(500);
    echo "DB not connected";
    exit;
}

$repdistrict = isset($_GET['repdistrict']) ? trim($_GET['repdistrict']) : '';
if ($repdistrict === '') {
    http_response_code(400);
    echo "repdistrict is required";
    exit;
}
$certPrefix = isset($_GET['prefix']) && $_GET['prefix'] !== '' ? $_GET['prefix'] : 'TNDT2025/';
$appnosCsv  = isset($_GET['appnos']) ? trim($_GET['appnos']) : '';

$filename = 'certificate_list_full_' . preg_replace('/[^A-Za-z0-9_-]/', '_', $repdistrict) . '_' . date('Ymd_His') . '.csv';
header('Content-Disposition: attachment; filename="'.$filename.'"');

// BOM for Excel UTF-8
echo "\xEF\xBB\xBF";

// ---- Championships date (optional reference for age calc) ----
$champDate = '';
if ($st = mysqli_prepare($con, "SELECT dates FROM championships WHERE district=? ORDER BY id DESC LIMIT 1")) {
    mysqli_stmt_bind_param($st, "s", $repdistrict);
    mysqli_stmt_execute($st);
    mysqli_stmt_store_result($st);
    mysqli_stmt_bind_result($st, $champDate);
    mysqli_stmt_fetch($st);
    mysqli_stmt_close($st);
}

// ---- Event columns & pretty headers ----
$quadKeys   = array('rink1','rink2','rink3','road1','road2');
$inlineKeys = array('rink4','rink5','rink6','rink7','p2p','elim','road3','road4','road5','p2prd','elimrd','relay','mixedrelay','marathon');
$artKeys    = array('figure','free','pair','solodance','pairdance','inlinefree','quartet','precisionskating','showgroup');
$hokKeys    = array('quadhockey','mixedrollerhockey'); // Roller-Hockey
$ihkKeys    = array('inlinehockey');                   // Inline-Hockey
$frKeys     = array('speedslalom','classicslalom','pairslalom'); // Inline-Freestyle
$othKeys    = array('alpine','downhill','rollerderby','rollerfreestylepark','rollerfreestylestreet','skateboardingpark','skateboardingstreet','scooterpark','scooterstreet'); // Other-Games

// For a consistent CSV (single header), include ALL event columns:
$allEventCols = array_merge($quadKeys,$inlineKeys,$artKeys,$hokKeys,$ihkKeys,$frKeys,$othKeys);

// Pretty names (same style you’ve used in certificates)
$pretty = array(
  // Speed-Quad
  'rink1'=>'RINK - I', 'rink2'=>'RINK - II', 'rink3'=>'RINK - III', 'road1'=>'ROAD - I', 'road2'=>'ROAD - II',
  // Speed-Inline
  'rink4'=>'RINK - IV', 'rink5'=>'RINK - V', 'rink6'=>'RINK - VI', 'rink7'=>'RINK - VII (Dual TT)',
  'p2p'=>'POINTS (TRACK)', 'elim'=>'ELIMINATION (RINK)',
  'road3'=>'ROAD - III', 'road4'=>'ROAD - IV', 'road5'=>'ROAD - V',
  'p2prd'=>'POINT TO POINT (ROAD)', 'elimrd'=>'ELIMINATION (ROAD)',
  'relay'=>'RELAY', 'mixedrelay'=>'MIXED RELAY', 'marathon'=>'MARATHON',
  // Artistic
  'figure'=>'FIGURE', 'free'=>'FREE', 'pair'=>'PAIR', 'solodance'=>'SOLO DANCE', 'pairdance'=>'PAIR DANCE', 'inlinefree'=>'INLINE FREE',
  'quartet'=>'QUARTET', 'precisionskating'=>'PRECISION', 'showgroup'=>'SHOW GROUP',
  // Hockey
  'quadhockey'=>'ROLLER HOCKEY', 'mixedrollerhockey'=>'MIXED ROLLER HOCKEY',
  // Inline-Hockey
  'inlinehockey'=>'INLINE HOCKEY',
  // Inline-Freestyle
  'speedslalom'=>'SPEED SLALOM', 'classicslalom'=>'CLASSIC SLALOM', 'pairslalom'=>'PAIR SLALOM',
  // Other-Games
  'alpine'=>'ALPINE','downhill'=>'DOWNHILL','rollerderby'=>'ROLLER DERBY','rollerfreestylepark'=>'ROLLER FREESTYLE - PARK',
        'skateboardingpark'=>'SKATEBOARDING - PARK','scooterpark'=>'SCOOTER-PARK','rollerfreestylestreet'=>'ROLLER FREESTYLE - STREET',
        'skateboardingstreet'=>'SKATEBOARDING - STREET','scooterstreet'=>'SCOOTER-STREET'
);

// Discipline groupings
$discMaps = array(
    'Speed-Quad'       => $quadKeys,
    'Speed-Inline'     => $inlineKeys,
    'Artistic'         => $artKeys,
    'Roller-Hockey'    => $hokKeys,
    'Inline-Hockey'    => $ihkKeys,
    'Inline-Freestyle' => $frKeys,
    'Other-Games'      => $othKeys
);
$discOrder = array(
    'Speed-Quad' => 1,
    'Speed-Inline' => 2,
    'Artistic' => 3,
    'Roller-Hockey' => 4,
    'Inline-Hockey' => 5,
    'Inline-Freestyle' => 6,
    'Other-Games' => 7
);

// ---- Helpers (PHP 5.6) ----
function label_code($v) {
    $v = strtoupper(trim((string)$v));
    if ($v==='1' || $v==='G') return 'FIRST';
    if ($v==='2')              return 'SECOND';
    if ($v==='3' || $v==='B') return 'THIRD';
    if ($v==='S')             return 'SELECTED';
    if ($v==='F')             return 'FORWARD';
    if ($v==='P')             return 'PARTICIPATED';
    if ($v==='A' || $v==='NR')return 'ABSENT';
    if ($v==='')              return 'NIL';
    return 'NIL';
}
function gender_word($g) {
    $g = strtolower(trim((string)$g));
    if (in_array($g, array('f','female','girl','girls','women','woman'), true)) return 'Girls';
    if (in_array($g, array('m','male','boy','boys','men','man'), true))         return 'Boys';
    return ucfirst($g);
}
function status_rank_for_cert($lbl) {
    // For Cert Type per discipline
    if ($lbl==='FIRST' || $lbl==='SECOND' || $lbl==='THIRD') return 70; // Merit
    if ($lbl==='SELECTED')  return 50;
    if ($lbl==='FORWARD')   return 40;
    if ($lbl==='PARTICIPATED') return 30;
    if ($lbl==='ABSENT')    return 10;
    return 0; // NIL
}
function compute_age_years($ageStr, $dobStr, $eventDateStr) {
    $age = (int)$ageStr;
    if ($age > 0) return $age;
    $dobTs = strtotime($dobStr);
    if (!$dobTs) return 0;
    $refTs = strtotime($eventDateStr);
    if (!$refTs) $refTs = time();
    $y1 = (int)date('Y',$refTs); $m1=(int)date('n',$refTs); $d1=(int)date('j',$refTs);
    $y0 = (int)date('Y',$dobTs); $m0=(int)date('n',$dobTs); $d0=(int)date('j',$dobTs);
    $age = $y1 - $y0;
    if ($m1 < $m0 || ($m1==$m0 && $d1 < $d0)) $age--;
    return ($age<0?0:$age);
}
function special_agegroup_for_row($discipline, $eventKey, $ageYears) {
    $age = (int)$ageYears;
    if ($discipline === 'Roller-Hockey' || $discipline === 'Inline-Hockey') {
        if ($age >= 6 && $age < 9)  return '6 to 9 Cadet Tiny Tots';
        if ($age >= 9 && $age < 12) return '9 to 12 Cadet';
        return null;
    }
    if ($eventKey === 'rollerderby') {
        if ($age >= 12 && $age < 18) return '12 to 18 Junior';
        return null;
    }
    if ($eventKey === 'scooter') {
        if ($age >= 12) return 'Above 12';
        return null;
    }
    return null;
}
function certificate_type_for($labelsInDiscipline) {
    // Decide from best label in that discipline
    $best = 'NIL'; $bestR = 0;
    foreach ($labelsInDiscipline as $lbl) {
        $r = status_rank_for_cert($lbl);
        if ($r > $bestR) { $bestR = $r; $best = $lbl; }
    }
    if ($best==='FIRST' || $best==='SECOND' || $best==='THIRD') return 'Merit';
    if ($best==='SELECTED')  return 'Selected';
    if ($best==='FORWARD')   return 'Forward';
    if ($best==='PARTICIPATED') return 'Participation';
    if ($best==='ABSENT')    return 'Absent';
    return 'Nil';
}

// ---- Build SQL ----
$cols = array_merge(
    array('appno','sname','gender','agegroup','age','dob','club','clubname','agorder','skatertype'),
    $allEventCols
);
$select = '`'.implode('`,`',$cols).'`';

$where = "order_status='Success' AND repdistrict='".mysqli_real_escape_string($con, $repdistrict)."'";
if ($appnosCsv !== '') {
    $parts = explode(',', $appnosCsv);
    $ins = array();
    foreach ($parts as $p) {
        $p = trim($p);
        if ($p!=='') $ins[] = "'".mysqli_real_escape_string($con,$p)."'";
    }
    if (!empty($ins)) $where .= " AND appno IN (".implode(',', $ins).")";
}

$sql = "
  SELECT $select
  FROM applications
  WHERE $where
  ORDER BY
    IFNULL(NULLIF(clubname,''), club),
    FIELD(skatertype,
      'Speed-Quad','Speed-Inline','Artistic','Roller-Hockey','Inline-Hockey','Inline-Freestyle','Other','Other-Games'
    ),
    IFNULL(agorder,999999)+0,
    gender DESC,
    CAST(appno AS UNSIGNED), appno
";

$res = mysqli_query($con, $sql);
if (!$res) {
    echo "Query failed: ".mysqli_error($con);
    exit;
}

// ---- Build rows ----
$rowsOut = array();

while ($r = mysqli_fetch_assoc($res)) {
    $team = ($r['clubname'] !== '') ? $r['clubname'] : $r['club'];
    $ageYears = compute_age_years(isset($r['age'])?$r['age']:'', isset($r['dob'])?$r['dob']:'', $champDate);
    $genderLbl = gender_word($r['gender']);
    $agorder = isset($r['agorder']) ? (int)$r['agorder'] : 999999;
    $appno = (string)$r['appno'];
    $name  = (string)$r['sname'];
    $skType= (string)$r['skatertype'];
    $agRaw = (string)$r['agegroup'];

    // Compute labels for all event columns once
    $labelsAll = array();
    $sawAny=false; $sawPositive=false; $sawAbsent=false;
    foreach ($allEventCols as $ek) {
        $lbl = label_code(isset($r[$ek]) ? $r[$ek] : '');
        $labelsAll[$ek] = $lbl;
        if ($lbl !== 'NIL') { $sawAny = true; }
        if ($lbl === 'ABSENT') $sawAbsent = true;
        if (in_array($lbl, array('FIRST','SECOND','THIRD','PARTICIPATED','SELECTED','FORWARD'), true)) $sawPositive = true;
    }

    if (!$sawAny) {
        // no event info at all; skip (clean CSV)
        continue;
    }

    if (!$sawPositive && $sawAbsent) {
        // Fully absent overall: include ONE row (discipline from skatertype) and show all events
        $discName = array_key_exists($skType, $discOrder) ? $skType : 'Speed-Quad';
        $discWeight = isset($discOrder[$discName]) ? $discOrder[$discName] : 99;

        // special age group (use derby/scooter keys if that discipline)
        $someKey = '';
        if ($discName==='Other-Games') {
            // pick a representative for special rule
            if ($labelsAll['rollerderby']!=='NIL') $someKey='rollerderby';
            elseif ($labelsAll['scooter']!=='NIL') $someKey='scooter';
        }
        $agOverride = special_agegroup_for_row($discName, $someKey, $ageYears);
        $agDisplay  = ($agOverride !== null && $agOverride !== '') ? $agOverride : $agRaw;

        $row = array(
            'team' => $team, 'disc'=>$discName, 'discW'=>$discWeight,
            'agorder'=>$agorder, 'gender'=>$r['gender'], 'genderLbl'=>$genderLbl,
            'certNo'=>$certPrefix.$appno, 'appno'=>$appno, 'name'=>$name,
            'ageGroupDisplay'=>$agDisplay, 'certType'=>'Absent'
        );
        // populate all event columns with their labels
        foreach ($allEventCols as $ek) $row[$ek] = $labelsAll[$ek];
        $rowsOut[] = $row;
        continue;
    }

    // Otherwise: emit one row PER discipline with ALL event columns, filling only its own
    foreach ($discMaps as $discName => $keys) {
        // check if participant has any non-NIL value in this discipline
        $hasAnyInDisc = false;
        $labelsInDisc = array();
        foreach ($keys as $ek) {
            $lbl = $labelsAll[$ek];
            $labelsInDisc[$ek] = $lbl;
            if ($lbl !== 'NIL') $hasAnyInDisc = true;
        }
        if (!$hasAnyInDisc) continue;

        $discWeight = isset($discOrder[$discName]) ? $discOrder[$discName] : 99;

        // Decide certificate type for this discipline
        $certType = certificate_type_for($labelsInDisc);

        // Special age label (hockey / derby / scooter)
        $reprKey = '';
        if ($discName==='Other-Games') {
            if ($labelsAll['rollerderby']!=='NIL') $reprKey='rollerderby';
            elseif ($labelsAll['scooter']!=='NIL') $reprKey='scooter';
        }
        $agOverride = special_agegroup_for_row($discName, $reprKey, $ageYears);
        $agDisplay  = ($agOverride !== null && $agOverride !== '') ? $agOverride : $agRaw;

        $row = array(
            'team'=>$team, 'disc'=>$discName, 'discW'=>$discWeight,
            'agorder'=>$agorder, 'gender'=>$r['gender'], 'genderLbl'=>$genderLbl,
            'certNo'=>$certPrefix.$appno, 'appno'=>$appno, 'name'=>$name,
            'ageGroupDisplay'=>$agDisplay, 'certType'=>$certType
        );
        // Fill this discipline's event labels; leave others empty for clarity
        foreach ($allEventCols as $ek) {
            $row[$ek] = in_array($ek,$keys,true) ? $labelsAll[$ek] : '';
        }
        $rowsOut[] = $row;
    }
}
mysqli_free_result($res);

// ---- Final sort ----
usort($rowsOut, function($a,$b){
    if ($a['team'] !== $b['team']) return strcasecmp($a['team'], $b['team']);
    if ($a['discW'] !== $b['discW']) return ($a['discW'] < $b['discW']) ? -1 : 1;
    if ($a['agorder'] !== $b['agorder']) return ($a['agorder'] < $b['agorder']) ? -1 : 1;
    // Girls before Boys
    $ga = strtolower(substr($a['gender'],0,1)); $gb = strtolower(substr($b['gender'],0,1));
    if ($ga !== $gb) return ($ga === 'f') ? -1 : 1;
    $na = (int)$a['appno']; $nb = (int)$b['appno'];
    if ($na !== $nb) return ($na < $nb) ? -1 : 1;
    return strcmp($a['appno'],$b['appno']);
});

// ---- CSV header ----
$out = fopen('php://output','w');
$header = array(
  'Sl.No','Cert No','App No','Name','Team','Discipline','Age Group (Printed)','Gender','Certificate Type'
);
// append ALL event columns (pretty names)
foreach ($allEventCols as $ek) {
    $header[] = isset($pretty[$ek]) ? $pretty[$ek] : strtoupper($ek);
}
fputcsv($out, $header);

// ---- CSV rows ----
$sl = 1;
foreach ($rowsOut as $row) {
    $line = array(
        $sl++,
        $row['certNo'],
        $row['appno'],
        $row['name'],
        $row['team'],
        $row['disc'],
        $row['ageGroupDisplay'].' - '.$row['genderLbl'].' Age Group',
        $row['genderLbl'],
        $row['certType']
    );
    foreach ($allEventCols as $ek) {
        $line[] = isset($row[$ek]) ? $row[$ek] : '';
    }
    fputcsv($out, $line);
}
fclose($out);
exit;
?>